GNU/Linux >> Linux Esercitazione >  >> Linux

Identificare il nome del segnale ricevuto in Bash

(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

Linux
  1. Riferimenti ai nomi circolari nella funzione Bash Shell, ma non in Ksh?

  2. Bash + Verifica nome tramite espressione regolare?

  3. 5 Esempi di dichiarazioni di Bash Case

  4. Python - Intrappola tutti i segnali

  5. Come posso annullare l'impostazione o eliminare una funzione bash?

Bash wait Comando

Bash mentre Loop

Funzioni Bash

Bash Shebang

Utili comandi Bash di cui potresti non essere a conoscenza

Linux Bash Scripting Part5 – Segnali e lavori