Bash scripting - segnali

Da Guide@Debianizzati.Org.

Bash scripting

Sommario

  1. Introduzione
  2. Comandi essenziali
  3. Variabili (stringhe)
  4. Caratteri di escape, apici e virgolette
  5. Espansioni in stringhe quotate
  6. Espansioni non quotabili
  7. Istruzioni composte
  8. Funzioni
  9. File descriptor e redirezioni
  10. Segnali

Indice

Ogni processo in Unix e Unix-like può ricevere dei segnali da altri processi (se appartengono allo stesso utente oppure da root). Di seguito i principali, tra quelli previsti da POSIX:

Il core dump è un dump dello stato (o una sua parte) del processo terminato, a scopo di debug. Può essere limitato e anche disattivato interamente. Se non attivo, l'azione eseguita è equivalente a una terminazione senza core dump.

Invio di segnali

Alcuni segnali vengono inviati automaticamente, al sussistere di determinate condizioni, ma possono anche essere inviati esplicitamente con il comando kill come tutti gli altri.
Sintassi: kill [ -s SIGNAL ] pid
Invia un segnale (di default: TERM) al processo con il PID scelto. Si noti che l'invio è asincrono, ossia kill non resta in attesa che il processo con PID scelto effettui l'azione associata al segnale. Di conseguenza il comando ha sempre successo, salvo che il PID non esista o non possa ricevere il segnale (per esempio perché non è dello stesso utente).

Cattura dei segnali

Le azioni da intraprendere possono essere modificati con l'istruzione trap.
Sintassi: trap 'stringa' SIGNAL1 [ ... ]
Cattura i segnali (se possibile, non lo è per KILL e STOP), con il seguente comportamento:

Warning.png ATTENZIONE
Al posto di 'stringa' nell'istruzione trap può esserci un qualsiasi comando, ma si consiglia l'uso di una funzione sia per chiarezza del codice, sia soprattutto per evitare la doppia interpretazione con possibili espansioni in fase di definizione di trap prima e di esecuzione del comando poi. Un uso diverso ha la stessa pericolosità di eval, e può portare a code injection e privilege escalation.


In caso di esecuzione di una subshell le azioni da intraprendere in seguito alla ricezione di un segnale vengono reimpostate al loro valore di default, ma i segnali ignorati continuano a restare ignorati.

Esempi

trap '' INT HUP QUIT TERM  # segnali standard di terminazione

Nota che KILL non può essere ignorato e nemmeno catturato, quindi in genere è sconsigliabile non prevedere una terminazione non brutale attraverso un segnale.

trap '' HUP
interrupt () {
    # fai qualcosa
    ...
    exit 127 # chiusura esplicita NECESSARIA
             # perché l'azione di default è sovrascritta
}

...

# esegue interrupt se uno dei segnali è ricevuto
# e poi esci (perché specificato in interrupt!)
trap 'interrupt' INT HUP QUIT TERM

...

exit 0       # non esegue interrupt
interrupt () {
    # fai qualcosa
    ...
    exit 127 # chiusura esplicita NECESSARIA
             # perché l'azione di default è sovrascritta
}

# ignora terminazione da tastiera
trap '' INT QUIT

# gestisci altri segnali di terminazione
trap 'interrupt' HUP TERM
clean () {
    # funzione di pulizia
    ...
    # NOTA: niente exit finale per evitare loop infinito
    # infatti è già richiamata da trap ... EXIT!
}

...

# la funzione clean è eseguita alla terminazione
trap 'clean' EXIT

# esci (codice 127), eseguendo clean,  alla ricezione di questi segnali
# non è necessario in bash, perché è implicito
trap 'exit 127' INT HUP QUIT TERM

...
if comando; then
    exec eseguibile # clean NON è eseguita dopo exec e un eseguibile
fi
...
exit 0              # clean è eseguita anche con exit
Strumenti personali
Namespace
Varianti
Azioni
Navigazione
Risorse
Strumenti