(Pokud máte pouze číslo signálu a chcete název, kill -l $SIGNAL_NUM
vypíše název signálu; tomu se můžete vyhnout tím, že při volání na číslo trap
použijete místo čísel názvy signálů jako níže.)
Tato odpověď říká, že neexistuje způsob, jak získat přístup k názvu signálu, ale pokud máte samostatnou funkci pro každý signál, který zachytíte, pak již název signálu znáte:
trap 'echo trapped the HUP signal' HUP
trap 'echo different trap for the INT signal' INT
V mnoha případech to může být dostačující, ale jiná odpověď na stejnou otázku využívá tuto skutečnost k poskytnutí řešení, jak předstírat chování, které chcete. Vezme funkci a seznam signálů a nastaví samostatnou past pro každý signál na této funkci nazývané jménem signálu, takže interně je to vlastně samostatná funkce pro každý signál, ale vypadá to jako jedna past na jedinou funkci, která dostane název signálu jako argument:
Kód:
#!/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.
Pokud to spustím, pak mohu poslat signály do procesu a dostanu výstup jako
Trapped: INT
Trapped: TERM
Trapped: EXIT
S odkazem na $?
řešení výše:$?
bude odrážet výstupní kód posledního provedeného příkazu. Zvažte toto:
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
sleep 3600
Pokud toto spustíte a stisknete Ctrl-C , vypíše CODE: 130
. Je to proto, že sleep
spustitelný soubor byl přerušen SIGINTem a ukončen s tímto kódem.
Porovnejte to s:
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
read X
Pokud toto spustíte a stisknete Ctrl-C , vytiskne CODE: 0
, pravděpodobně proto, že read
příkaz je vestavěný a pravidla ukončovacího kódu se liší (totéž se stane, pokud přerušíte while : ; do : ; done
).
Takže $?
informuje o signálu pouze v případě, že přerušil externí příkaz, a pokud tento konkrétní program nezachytil signál a neukončil se s vlastním výstupním kódem. Pointou je výše uvedený bash skript:po obdržení SIGINTu se ukončí s kódem 1
, nikoli 130
.
V pasti (když je spuštěna signálem), $? proměnná je zpočátku nastavena na číslo signálu plus 128, takže číslo signálu můžete přiřadit proměnné provedením prvního příkazu akce past něco jako
sig=$(($? - 128))
Název signálu pak můžete získat pomocí příkazu kill
kill -l $sig
Aktualizace:Jak je uvedeno v komentářích, toto nefunguje pro některé vestavěné příkazy shellu. Aby tito nastavili past $? proměnné, mohou být spuštěny v subshell, Eg
(read)
místo
read
jednoduchý způsob, jak to udělat:
_handler() {
signal=$1
echo signal was $signal
}
trap '_handler SIGTERM' SIGTERM
trap '_handler SIGINT' SIGINT