Risposte:
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"
Puoi assicurarti che un file venga eliminato quando escono gli script (inclusi uccisioni e arresti anomali) aprendo un descrittore di file al file ed eliminandolo. Il file rimane disponibile (per lo script; non proprio per altri processi ma /proc/$PID/fd/$FD
è una soluzione) finché il descrittore di file è aperto. Quando viene chiuso (cosa che il kernel fa automaticamente all'uscita dal processo) il filesystem cancella il file.
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
exec 3>"$tmpfile"
rm "$tmpfile"
: ...
echo foo >&3
/proc
- ad eccezione dei sistemi che non lo hanno.
exec 3> "$tmpfile"
? Non è utile solo se il file tmp è uno script autonomo?
cat <&3
darà Bad file descriptor
. Lo apprezzerei se lo riparassi o lo rimuovessi; la disinformazione non aiuta molto.
Utilizzare mktemp
per creare un file o una directory temporaneo:
temp_file=$(mktemp)
O per una regia:
temp_dir=$(mktemp -d)
Alla fine dello script devi eliminare il file / dir temporaneo:
rm ${temp_file}
rm -R ${temp_dir}
mktemp crea il file nella /tmp
directory o nella directory indicata con l' --tmpdir
argomento.
trap "rm -f $temp_file" 0 2 3 15
subito dopo aver creato il file in modo che quando lo script viene chiuso o interrotto con ctrl-C
il file sia ancora rimosso.
EXIT
è l'unico hook per trap
?
kill -9 $somepid
. Quel particolare segnale di uccisione è insta-morte con nient'altro che accade.
bash -c 'echo $$; trap "echo foo" 0; sleep 5'
EXIT
è abbastanza.
Se sei su un sistema che ha mktemp , dovresti usarlo come altre risposte.
Con il toolchest POSIX:
umask 0177
tmpfile=/tmp/"$0"."$$"."$(awk 'BEGIN {srand();printf "%d\n", rand() * 10^10}')"
trap 'rm -f -- "$tmpfile"' INT TERM HUP EXIT
: > "$tmpfile"
EXIT
è l'unico gancio per trap
?
tmpfile
essere comunque rimosso prima dell'uscita dello script, ma non quando lo script ha ricevuto altri segnali.
That's not what happens
?
mktemp
originato in HP / UX con una sintassi diversa. Todd C. Miller ne creò uno diverso per OpenBSD a metà degli anni '90 (copiato da FreeBSD e NetBSD) e in seguito lo rese disponibile anche come utility standalone (www.mktemp.org). Questo è quello che è stato generalmente utilizzato su Linux fino a quando mktemp
un'utilità (per lo più compatibile) è stata aggiunta ai coreutils GNU nel 2007. Solo per dire che non si può davvero dire che mktemp
è un'utilità GNU.
Alcune shell hanno la funzione integrata.
zsh
La =(...)
forma di sostituzione del processo utilizza un file temporaneo. Ad esempio, si =(echo test)
espande nel percorso di un file temporaneo che contiene test\n
.
$ {cat $file; ls -l /dev/fd/3; echo test2 >&3; cat $file} 3<> ${file::==(echo test)}
test
lrwx------ 1 stephane stephane 64 Jan 30 11:19 /dev/fd/3 -> /tmp/zshMLbER0
test2
Tale file viene automaticamente rimosso, al termine del comando.
Here-files o here-string in bash
e zsh
vengono implementati come file temporanei eliminati.
Quindi se lo fai:
exec 3<<< test
Il descrittore di file 3 è collegato a un file temporaneo eliminato che contiene test\n
.
Puoi ottenere il suo contenuto con:
cat <&3
Se su Linux, puoi anche leggere o scrivere su quel file tramite /dev/fd/3
$ exec 3<<< test
$ cat <&3
test
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo
(alcune altre shell usano pipe o possono usare /dev/null
se il documento qui è vuoto).
Non esiste alcuna mktemp
utilità POSIX. POSIX specifica tuttavia mkstemp(template)
un'API C e l' m4
utilità standard espone tale API con la mkstemp()
funzione m4 con lo stesso nome.
mkstemp()
ti dà un nome di file con una parte casuale che era garantita non esistere al momento della chiamata della funzione. Crea il file con i permessi 0600 in un modo senza gara.
Quindi, potresti fare:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
Si noti tuttavia che è necessario gestire la pulizia all'uscita, anche se se si deve solo scrivere e leggere il file un numero fisso di volte, è possibile aprirlo ed eliminarlo subito dopo aver creato come per here-doc / here- approccio stringa sopra:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
# open once for writing, twice for reading:
exec 3> "$tempfile" 4< "$tempfile" 5< "$tempfile"
rm -f -- "$tmpfile"
cmd >&3 # store something in the temp file
exec 3>&- # fd no longer needed
# read the content twice:
cat <&4
cat <&5
È possibile aprire il file per la lettura una volta e riavvolgere tra due letture, tuttavia non esiste un'utilità POSIX in grado di eseguire tale riavvolgimento ( lseek()
), quindi non è possibile farlo in uno script POSIX ( zsh
( sysseek
incorporato) e ksh93
( <#((...))
operatore) possono fallo però).
<()
=(...)
.
Ecco una risposta leggermente migliorata nella linea di Hauke Laging:
#!/bin/bash
tmpfile=$(mktemp) # Create a temporal file in the default temporal folder of the system
# Lets do some magic for the tmpfile to be removed when this script ends, even if it crashes
exec {FD_W}>"$tmpfile" # Create file descriptor for writing, using first number available
exec {FD_R}<"$tmpfile" # Create file descriptor for reading, using first number available
rm "$tmpfile" # Delete the file, but file descriptors keep available for this script
# Now it is possible to work with the temporal file
echo foo >&$FD_W
echo bar >&$FD_W # Note that file descriptor always concatenates, not overwrites
cat <&$FD_R
Il mio flusso di lavoro in genere con i file temporanei è a causa di alcuni script bash che sto testando. Lo voglio in tee
modo da poter vedere che funziona e salvare l'output per la prossima iterazione del mio processo. Ho creato un file chiamatotmp
#!/bin/bash
echo $(mktemp /tmp/$(date +"%Y-%m-%d_%T_XXXXXX"))
in modo che io possa usarlo come
$ some_command --with --lots --of --stuff | tee $(tmp)
Il motivo per cui mi piace il datetime formattato prima dei valori casuali è che mi permette di trovare il file tmp che ho appena creato facilmente e non devo pensare a come nominarlo la prossima volta (e concentrarmi solo su come ottenere il mio script dang lavorare).