2011-11-14 5 views
24

Vedo un sacco di script di shell che fare:È necessario specificare trap diversi da EXIT?

 
trap cmd 0 1 2 3 13 15 # EXIT HUP INT QUIT PIPE TERM 

In ogni guscio Ho accesso a in questo momento, tutte le trappole diversi da 0 sono ridondanti, e cmd verrà eseguito al momento della ricezione di un segnale, se la trappola viene semplicemente specificata:

 
trap cmd 0 

La seconda specifica è sufficiente oppure alcune shell richiedono che gli altri segnali siano specificati?

risposta

15

Per assicurarsi che il gestore di segnale EXIT non venga eseguito due volte (che quasi sempre non è quello che si desidera), deve sempre essere impostato per essere ignorato o ripristinato all'interno della definizione del gestore di segnale EXIT stesso.

Lo stesso vale per i segnali che hanno più di un gestore di segnale definito per loro in un programma.

# reset 
trap 'excode=$?; cmd; trap - EXIT; echo $excode' EXIT HUP INT QUIT PIPE TERM 

# ignore 
trap 'excode=$?; trap "" EXIT; cmd; echo $excode' EXIT HUP INT QUIT PIPE TERM 
+0

Questa è una buona idea. Non credo sia necessario preoccuparsi dei segnali con più di una trappola definita, dal momento che è possibile definire solo una trappola per segnale. (La seconda trappola sostituisce la prima, piuttosto che l'aggiunta a una pila.) Alcune shell consentono di definire più trap? –

+2

Ero sotto la stessa confusione di @WilliamPursell fino a quando ho finalmente notato "ignorato ** o ** reset". –

13

Penso che trap 0 sia eseguito appena prima della terminazione dello script in tutti i casi, quindi è utile per la funzionalità di pulizia (come la rimozione di file temporanei, ecc.). Gli altri segnali possono avere una gestione specializzata degli errori, ma dovrebbero terminare lo script (cioè, call exit).

Quello che hai descritto, credo, eseguirà effettivamente cmd due volte. Una volta per il segnale (ad esempio SIGTERM) e ancora una volta in uscita (trap 0).

Credo che il modo corretto per farlo è simile al seguente (vedi specifiche POSIX per trap):

trap "rm tmpfile" 0 
trap "exit 1" TERM HUP ... 

Questo assicura un file temporaneo viene rimosso dopo il completamento dello script, e consente di impostare gli stati di uscita personalizzato segnali.

NOTA: trap 0 viene chiamato se viene rilevato o meno un segnale.

Se non si è interessati all'impostazione di uno stato di uscita, il trap 0 sarebbe sufficiente.

5

Lo standard di shell non specifica se una trap su 0 viene eseguita quando viene ricevuto un segnale non in trappola. In particolare, bash e dash si comportano diversamente. Dato trap cmd-list 0 senza set di trap per alcun segnale, bash eseguirà l'elenco cmd al ricevimento di SIGTERM, ma il trattino no. Dato trap cmd-list 0 2, bash esegue cmd-list una volta al momento della ricezione di SIGTERM e dash esegue due volte cmd-list.

+2

Quindi la risposta migliore è una combinazione di questo e Brandon Horsley di: per la portabilità, non date per scontato che il 'trappola ... 0' sarà eseguito SIGTERM, e non date per scontato che ha vinto 't. Crea un'uscita separata "trap" 1 "SIGTERM ..." per garantire che lo farà. – dubiousjim