(Wenn Sie nur die Nummer eines Signals haben und den Namen wollen, kill -l $SIGNAL_NUM
druckt den Namen eines Signals; Sie können dies vermeiden, indem Sie die Signalnamen anstelle von Nummern in Ihrem Aufruf an trap
verwenden wie unten.)
Diese Antwort besagt, dass es keine Möglichkeit gibt, auf den Signalnamen zuzugreifen, aber wenn Sie für jedes Signal, das Sie abfangen, eine separate Funktion haben, kennen Sie den Signalnamen bereits:
trap 'echo trapped the HUP signal' HUP
trap 'echo different trap for the INT signal' INT
In vielen Fällen mag das ausreichen, aber eine andere Antwort auf dieselbe Frage nutzt diese Tatsache, um eine Problemumgehung bereitzustellen, um das gewünschte Verhalten vorzutäuschen. Es nimmt eine Funktion und eine Liste von Signalen und setzt eine separate Falle für jedes Signal auf dieser Funktion, die mit dem Signalnamen aufgerufen wird, also ist es intern eigentlich eine separate Funktion für jedes Signal, aber es sieht aus wie eine einzelne Falle für eine einzelne Funktion, die die erhält Signalname als Argument:
Code:
#!/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.
Wenn ich das ausführe, kann ich Signale an den Prozess senden und bekomme eine Ausgabe wie
Trapped: INT
Trapped: TERM
Trapped: EXIT
Bezugnehmend auf $?
obige Lösung:$?
gibt den Exit-Code des zuletzt ausgeführten Befehls wieder. Bedenken Sie Folgendes:
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
sleep 3600
Wenn Sie dies ausführen und Strg-C drücken , es wird CODE: 130
ausgegeben . Das liegt daran, dass sleep
ausführbare Datei wurde durch SIGINT unterbrochen und mit diesem Code beendet.
Vergleichen Sie das mit:
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
read X
Wenn Sie dies ausführen und Strg-C drücken , es wird CODE: 0
ausgegeben , vermutlich weil die read
Der Befehl ist ein eingebauter Befehl und die Exit-Code-Regeln sind unterschiedlich (dasselbe passiert, wenn Sie while : ; do : ; done
unterbrechen würden ).
Also $?
informiert Sie nur über das Signal, wenn es einen externen Befehl unterbrochen hat, und wenn dieses bestimmte Programm das Signal nicht abgefangen und mit seinem eigenen Exit-Code beendet hat. Point-in-Case ist das obige Bash-Skript:Beim Empfang eines SIGINT wird es mit dem Code 1
beendet , nicht 130
.
Innerhalb der Falle (wenn sie über ein Signal ausgelöst wird) wird das $? Die Variable ist anfänglich auf die Signalnummer plus 128 gesetzt, sodass Sie die Signalnummer einer Variablen zuweisen können, indem Sie die erste Anweisung der Trap-Aktion auf etwas wie
setzensig=$(($? - 128))
Sie können dann den Namen des Signals mit dem Kill-Befehl abrufen
kill -l $sig
Update:Wie in den Kommentaren erwähnt, funktioniert dies für einige eingebaute Shell-Befehle nicht. Damit diese das $ der Falle stellen? Variable, sie können in einer Subshell ausgeführt werden, zB
(read)
statt
read
ein einfacher Weg, dies zu tun:
_handler() {
signal=$1
echo signal was $signal
}
trap '_handler SIGTERM' SIGTERM
trap '_handler SIGINT' SIGINT