Rimozione dei file temporanei creati in uscita bash inaspettato
-
22-08-2019 - |
Domanda
sto creando i file temporanei da uno script bash. Sto eliminarli al termine del trattamento, ma dal momento che lo script è in esecuzione per un periodo piuttosto lungo, se uccido o semplicemente CTRL-C durante la corsa, i file temporanei non vengono eliminate.
C'è un modo per catturare quegli eventi e la bonifica dei file prima dell'esecuzione finisce?
Inoltre, c'è una sorta di best practice per la denominazione e la posizione di quei file temporanei?
Non sono attualmente sicuro tra l'utilizzo di:
TMP1=`mktemp -p /tmp`
TMP2=`mktemp -p /tmp`
...
e
TMP1=/tmp/`basename $0`1.$$
TMP2=/tmp/`basename $0`2.$$
...
O forse c'è qualche soluzioni migliori?
Soluzione
È possibile impostare un " trappola " per eseguire il uscire o su un controllo-c per ripulire.
trap "{ rm -f $LOCKFILE; }" EXIT
In alternativa, uno dei miei preferiti unix-ismi è quello di aprire un file, e quindi eliminarlo mentre hai ancora aperto. Il file rimane sul file system e si può leggere e scrivere, ma non appena il vostro programma esce, il file va via. Non sai come si farebbe che in bash, però.
A proposito: Un argomento darò a favore di mktemp invece di utilizzare la vostra soluzione: se l'utente anticipa il programma sta andando a creare enormi file temporanei, si potrebbe voler impostare TMPDIR
da qualche parte più grande, come / var / tmp . mktemp riconosce che, la soluzione arrotolato a mano (seconda opzione) non lo fa. Io uso spesso TMPDIR=/var/tmp gvim -d foo bar
, per esempio.
Altri suggerimenti
Io di solito creare una directory in cui collocare tutti i miei file temporanei, e poi subito dopo, creare un gestore EXIT per ripulire questa directory quando lo script esce.
MYTMPDIR=$(mktemp -d)
trap "rm -rf $MYTMPDIR" EXIT
Se si mettono tutti i file temporanei sotto $MYTMPDIR
, allora saranno tutti eliminati quando lo script esce in più circostanze. Uccidere un processo con SIGKILL (kill -9) uccide il processo subito, però, in modo che il gestore EXIT non verrà eseguito in quel caso.
Si desidera utilizzare il comando trappola per gestire l'uscita dello script o segnali come CTRL-C. Vedere Wiki di Greg per i dettagli.
Per i vostri file temporanei, utilizzando basename $0
è una buona idea, oltre a fornire un modello che fornisce la stanza per i file temporanei sufficienti:
tempfile() {
tempprefix=$(basename "$0")
mktemp /tmp/${tempprefix}.XXXXXX
}
TMP1=$(tempfile)
TMP2=$(tempfile)
trap 'rm -f $TMP1 $TMP2' EXIT
Basta tenere a mente che scelto risposta è bashism
, il che significa che la soluzione come
trap "{ rm -f $LOCKFILE }" EXIT
avrebbe funzionato solo in bash (che non prenderà Ctrl + c se shell è dash
o sh
classico), ma se volete la compatibilità allora avete ancora bisogno di elencare tutti i segnali che si vogliono intrappolare.
Anche tenere a mente che quando script esce la trappola per segnale "0" (EXIT alias) viene sempre effettuata con conseguente doppia esecuzione di comando trap
.
Che la ragione non impilare tutti i segnali in una linea se c'è segnale EXIT.
Per capire meglio guardare seguente script che funzionerà su sistemi diversi, senza modifiche:
#!/bin/sh
on_exit() {
echo 'Cleaning up...(remove tmp files, etc)'
}
on_preExit() {
echo
echo 'Exiting...' # Runs just before actual exit,
# shell will execute EXIT(0) after finishing this function
# that we hook also in on_exit function
exit 2
}
trap on_exit EXIT # EXIT = 0
trap on_preExit HUP INT QUIT TERM STOP PWR # 1 2 3 15 30
sleep 3 # some actual code...
exit
Questa soluzione vi darà un maggiore controllo in quanto è possibile eseguire alcune delle vostro codice al verificarsi di segnale effettivo poco prima uscita (funzione preExit
) finale e, se necessario, è possibile eseguire del codice a segnale di rimborso effettivamente (stadio finale di uscita)
L'alternativa di usare un nome di file prevedibile con $$ è un grosso problema di sicurezza e non si dovrebbe mai, mai, mai pensare di utilizzarlo. Anche se è solo un semplice script personali sul proprio PC singolo utente. Si tratta di una pessima abitudine non si deve ottenere. BugTraq è pieno di "di file temporaneo insicure" incidenti. Vedere qui , qui e qui per maggiori informazioni sul l'aspetto della sicurezza dei file temporanei.
Mi è stato inizialmente pensando di citare le assegnazioni tmp1 e tmp2 insicuri, ma ripensandoci che probabilmente non essere una buona idea .
Io preferisco usare tempfile
che crea un file in / tmp in modo sicuro e tu non devi preoccuparti di sua denominazione:
tmp=$(tempfile -s "your_sufix")
trap "rm -f '$tmp'" exit
Non c'è bisogno di preoccuparsi di rimuovere i file TMP creati con mktemp. Essi verranno eliminati comunque in seguito.
Utilizzare mktemp se è possibile in quanto genera file più unico poi '$$' prefisso. E sembra che più modo cross platform per creare file temporanei poi esplicitamente metterli in / tmp.