GNU/Linux >> Znalost Linux >  >> Linux

Identifikace názvu přijatého signálu v Bash

(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

Linux
  1. Jak poznám název souboru skriptu ve skriptu Bash?

  2. Jak převést .. v názvech cest na absolutní název v bash skriptu?

  3. BASH:odeslání signálu SIGTSTP (ctrl+z)

  1. Kruhové odkazy na názvy ve funkci Bash Shell, ale ne v Ksh?

  2. Spusťte příkaz bash na jenkins pipeline

  3. Jak odstranit koncové znaky v názvech souborů v Bash?

  1. Bash + Ověřit název regulárním výrazem?

  2. 5 Příklady prohlášení o případu Bash

  3. Python - Zachyťte všechny signály