Unix / Linux - Segnali e trap

In questo capitolo, discuteremo in dettaglio di segnali e trap in Unix.

I segnali sono interruzioni software inviate a un programma per indicare che si è verificato un evento importante. Gli eventi possono variare dalle richieste dell'utente agli errori di accesso alla memoria illegale. Alcuni segnali, come il segnale di interruzione, indicano che un utente ha chiesto al programma di fare qualcosa che non rientra nel normale flusso di controllo.

La tabella seguente elenca i segnali comuni che potresti incontrare e che desideri utilizzare nei tuoi programmi:

Nome segnale Numero di segnale Descrizione
SIGHUP 1 Riagganciare rilevato sul terminale di controllo o morte del processo di controllo
SIGINT 2 Emesso se l'utente invia un segnale di interruzione (Ctrl + C)
SIGQUIT 3 Emesso se l'utente invia un segnale di chiusura (Ctrl + D)
SIGFPE 8 Emesso se viene tentata un'operazione matematica illegale
SIGKILL 9 Se un processo riceve questo segnale, deve chiudersi immediatamente e non eseguirà alcuna operazione di pulizia
SIGALRM 14 Segnale sveglia (utilizzato per i timer)
SIGTERM 15 Segnale di terminazione software (inviato da kill per impostazione predefinita)

Elenco dei segnali

C'è un modo semplice per elencare tutti i segnali supportati dal tuo sistema. Basta emettere il filekill -l comando e visualizzerà tutti i segnali supportati -

$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGSTKFLT
17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU
25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
29) SIGIO       30) SIGPWR      31) SIGSYS      34) SIGRTMIN
35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4
39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6
59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

L'elenco effettivo dei segnali varia tra Solaris, HP-UX e Linux.

Azioni predefinite

Ad ogni segnale è associata un'azione predefinita. L'azione predefinita per un segnale è l'azione che uno script o un programma esegue quando riceve un segnale.

Alcune delle possibili azioni predefinite sono:

  • Termina il processo.

  • Ignora il segnale.

  • Dump core. Questo crea un file chiamatocore contenente l'immagine di memoria del processo quando ha ricevuto il segnale.

  • Interrompi il processo.

  • Continua un processo interrotto.

Invio di segnali

Esistono diversi metodi per inviare segnali a un programma o uno script. Uno dei più comuni è che un utente digitiCONTROL-C o il INTERRUPT key mentre uno script è in esecuzione.

Quando si preme il pulsante Ctrl+C chiave, a SIGINT viene inviato allo script e come da script di azione predefinito definito termina.

L'altro metodo comune per fornire i segnali è utilizzare il kill command, la cui sintassi è la seguente -

$ kill -signal pid

Qui signal è il numero o il nome del segnale da trasmettere e pidè l'ID del processo a cui deve essere inviato il segnale. Ad esempio -

$ kill -1 1001

Il comando precedente invia il segnale HUP o di riaggancio al programma in esecuzione con process ID 1001. Per inviare un segnale di kill allo stesso processo, utilizzare il seguente comando:

$ kill -9 1001

Questo uccide il processo in esecuzione con process ID 1001.

Segnali di intrappolamento

Quando si preme il tasto Ctrl + C o Break sul terminale durante l'esecuzione di un programma shell, normalmente quel programma viene immediatamente terminato e il prompt dei comandi ritorna. Questo potrebbe non essere sempre desiderabile. Ad esempio, potresti finire per lasciare un mucchio di file temporanei che non verranno ripuliti.

Il trapping di questi segnali è abbastanza semplice e il comando trap ha la seguente sintassi:

$ trap commands signals

Qui command può essere qualsiasi comando Unix valido, o anche una funzione definita dall'utente, e signal può essere un elenco di qualsiasi numero di segnali che si desidera intercettare.

Ci sono due usi comuni per trap negli script di shell:

  • Elimina i file temporanei
  • Ignora i segnali

Pulizia dei file temporanei

Come esempio del comando trap, quanto segue mostra come rimuovere alcuni file e poi uscire se qualcuno cerca di interrompere il programma dal terminale -

$ trap "rm -f $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 2

Dal punto nel programma shell in cui viene eseguita questa trap, i due file work1$$ e dataout$$ verrà automaticamente rimosso se il segnale numero 2 viene ricevuto dal programma.

Quindi, se l'utente interrompe l'esecuzione del programma dopo che questa trap è stata eseguita, si può essere certi che questi due file verranno cancellati. Ilexit comando che segue il rm è necessario perché senza di esso l'esecuzione continuerebbe nel programma dal punto in cui si è interrotta quando è stato ricevuto il segnale.

Il segnale numero 1 viene generato per hangup. O qualcuno riattacca intenzionalmente la linea o la linea viene scollegata accidentalmente.

È possibile modificare la trappola precedente per rimuovere anche i due file specificati in questo caso aggiungendo il segnale numero 1 all'elenco dei segnali -

$ trap "rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 1 2

Ora questi file verranno rimossi se la linea viene interrotta o se viene premuto il tasto Ctrl + C.

I comandi specificati per trap devono essere racchiusi tra virgolette, se contengono più di un comando. Si noti inoltre che la shell esegue la scansione della riga di comando nel momento in cui viene eseguito il comando trap e anche quando viene ricevuto uno dei segnali elencati.

Pertanto, nell'esempio precedente, il valore di WORKDIR e $$verrà sostituito nel momento in cui viene eseguito il comando trap. Se si desidera che questa sostituzione avvenga nel momento in cui è stato ricevuto il segnale 1 o 2, è possibile inserire i comandi tra virgolette singole -

$ trap 'rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit' 1 2

Ignorare i segnali

Se il comando elencato per trap è nullo, il segnale specificato verrà ignorato quando ricevuto. Ad esempio, il comando -

$ trap '' 2

Questo specifica che il segnale di interruzione deve essere ignorato. Potresti voler ignorare alcuni segnali quando esegui un'operazione che non vuoi essere interrotta. È possibile specificare più segnali da ignorare come segue:

$ trap '' 1 2 3 15

Si noti che il primo argomento deve essere specificato affinché un segnale venga ignorato e non equivale a scrivere quanto segue, che ha un significato separato -

$ trap  2

Se ignori un segnale, anche tutte le subshell ignorano quel segnale. Tuttavia, se si specifica un'azione da intraprendere alla ricezione di un segnale, tutte le subshell eseguiranno comunque l'azione predefinita alla ricezione di quel segnale.

Ripristino delle trap

Dopo aver modificato l'azione predefinita da intraprendere alla ricezione di un segnale, è possibile modificarla nuovamente con la trappola se si omette semplicemente il primo argomento; così -

$ trap 1 2

Ciò ripristina l'azione da intraprendere alla ricezione dei segnali 1 o 2 al valore predefinito.