(Se hai solo il numero di un segnale e vuoi il nome, kill -l $SIGNAL_NUM
stampa il nome di un segnale; puoi evitarlo usando i nomi dei segnali invece dei numeri nella tua chiamata a trap
come di seguito.)
Questa risposta dice che non c'è modo di accedere al nome del segnale, ma se hai una funzione separata per ogni segnale che catturi, allora conosci già il nome del segnale:
trap 'echo trapped the HUP signal' HUP
trap 'echo different trap for the INT signal' INT
In molti casi, ciò potrebbe essere sufficiente, ma un'altra risposta alla stessa domanda utilizza questo fatto per fornire una soluzione alternativa per simulare il comportamento desiderato. Prende una funzione e un elenco di segnali e imposta una trappola separata per ogni segnale su quella funzione chiamata con il nome del segnale, quindi internamente è in realtà una funzione separata per ogni segnale ma sembra una singola trappola su una singola funzione che ottiene il nome del segnale come argomento:
Codice:
#!/bin/bash
trap_with_arg() {
func="$1" ; shift
for sig ; do
trap "$func $sig" "$sig"
done
}
func_trap() {
echo "Trapped: $1"
}
trap_with_arg func_trap INT TERM EXIT
echo "Send signals to PID $$ and type [enter] when done."
read # Wait so the script doesn't exit.
Se lo eseguo, posso inviare segnali al processo e ottengo un output come
Trapped: INT
Trapped: TERM
Trapped: EXIT
Riferendosi al $?
soluzione sopra:$?
rifletterà il codice di uscita dell'ultimo comando eseguito. Considera questo:
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
sleep 3600
Se lo esegui e premi Ctrl-C , stamperà CODE: 130
. Questo perché il sleep
eseguibile è stato interrotto dal SIGINT ed è terminato con quel codice.
Confrontalo con:
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
read X
Se lo esegui e premi Ctrl-C , stamperà CODE: 0
, presumibilmente perché il read
Il comando è integrato e le regole del codice di uscita sono diverse (lo stesso accade se interrompi while : ; do : ; done
).
Quindi, $?
ti dice del segnale solo se ha interrotto un comando esterno, e se quel particolare programma non ha catturato il segnale ed è uscito con il proprio codice di uscita. Il punto nel caso in cui sia lo script bash sopra:dopo aver ricevuto un SIGINT, uscirà con il codice 1
, non 130
.
All'interno della trappola (quando attivato tramite un segnale), il $? La variabile è inizialmente impostata sul numero del segnale più 128, quindi puoi assegnare il numero del segnale a una variabile effettuando la prima istruzione dell'azione trap a qualcosa di simile
sig=$(($? - 128))
Puoi quindi ottenere il nome del segnale usando il comando kill
kill -l $sig
Aggiornamento:come notato nei commenti, questo non funziona per alcuni comandi della shell incorporati. Per avere questi set $ della trappola? variabile, possono essere eseguiti in una subshell, ad esempio
(read)
invece di
read
un modo semplice per farlo:
_handler() {
signal=$1
echo signal was $signal
}
trap '_handler SIGTERM' SIGTERM
trap '_handler SIGINT' SIGINT