bitlvl
IT

Riferimento dei segnali Linux

Scrivi un nome o un numero per trovare un segnale. L’ultima colonna è il codice di uscita che una shell riporta quando un processo muore per quel segnale (128 + numero). La tabella è in inglese.

 
N.NomePredefinitaSignificato / causaCodice di uscita
1SIGHUPTerminateHangup: the controlling terminal closed. Daemons reuse it to mean “reload configuration”.129
2SIGINTTerminateInterrupt from the keyboard (Ctrl-C).130
3SIGQUITCore dumpQuit from the keyboard (Ctrl-\); dumps core.131
4SIGILLCore dumpIllegal instruction.132
5SIGTRAPCore dumpTrace/breakpoint trap (debuggers).133
6SIGABRTCore dumpAbort signal from abort().134
7SIGBUSCore dumpBus error: bad memory access (alignment, mmap).135
8SIGFPECore dumpFloating-point exception, including integer divide by zero.136
9SIGKILLTerminateKill signal. Cannot be caught, blocked or ignored. Last resort; the process gets no chance to clean up.137
10SIGUSR1TerminateUser-defined signal 1. nginx: reopen logs; dd: print progress; Apache: graceful restart.138
11SIGSEGVCore dumpSegmentation fault: invalid memory reference.139
12SIGUSR2TerminateUser-defined signal 2. nginx: binary upgrade; Gunicorn: re-exec.140
13SIGPIPETerminateWrite to a pipe with no reader. Default kills the process, which is why `yes | head` stops.141
14SIGALRMTerminateTimer signal from alarm().142
15SIGTERMTerminateTermination request. The default for kill, systemd stop and docker stop; programs should catch it and shut down cleanly.143
16SIGSTKFLTTerminateStack fault on coprocessor (unused).144
17SIGCHLDIgnoreChild stopped or terminated.145
18SIGCONTContinueContinue if stopped (fg, kill -CONT).146
19SIGSTOPStopStop the process. Cannot be caught or ignored.147
20SIGTSTPStopStop typed at the terminal (Ctrl-Z).148
21SIGTTINStopBackground process tried to read from the terminal.149
22SIGTTOUStopBackground process tried to write to the terminal.150
23SIGURGIgnoreUrgent data on a socket.151
24SIGXCPUCore dumpCPU time limit exceeded.152
25SIGXFSZCore dumpFile size limit exceeded.153
26SIGVTALRMTerminateVirtual alarm clock.154
27SIGPROFTerminateProfiling timer expired.155
28SIGWINCHIgnoreTerminal window size changed.156
29SIGIOTerminateI/O now possible (asynchronous I/O).157
30SIGPWRTerminatePower failure.158
31SIGSYSCore dumpBad system call: the seccomp filter rejected a syscall (systemd SystemCallFilter=, Docker default profile).159

I risultati e i messaggi di questo strumento sono mostrati in inglese.

Cos’è un segnale

Un segnale è un messaggio di una parola che il kernel consegna a un processo: «il terminale si è chiuso», «hai toccato memoria non valida», «per favore fermati». Il processo può installare un handler per la maggior parte di essi, ignorarli, o accettare l’azione predefinita, che di solito è terminare (a volte con un core dump). Due non possono essere catturati né ignorati: SIGKILL termina il processo sul posto e SIGSTOP lo congela.

TERM contro KILL

kill PID invia SIGTERM: una richiesta. Un programma ben scritto lo cattura, finisce la richiesta corrente, svuota i file, chiude le connessioni ed esce; è ciò che systemd, Docker e Kubernetes inviano per primo. kill -9 invia SIGKILL: il kernel rimuove il processo senza eseguire alcun suo codice, quindi i lock restano presi, i file temporanei restano, e le scritture in corso vanno perse. Usalo solo dopo che a TERM è stato dato tempo (systemd aspetta TimeoutStopSec, Docker 10 secondi di default) e ha fallito.

I segnali come API

  • SIGHUP: i demoni ricaricano la configurazione (nginx, sshd, HAProxy con semantica -sf tramite reload di systemd). Per un processo in primo piano significa che il terminale è sparito; nohup lo ignora.
  • SIGUSR1 / SIGUSR2: definiti dal programma. nginx riapre i log su USR1 e aggiorna il binario su USR2; dd stampa l’avanzamento su USR1; Gunicorn e Unicorn li usano per i riavvii graceful.
  • SIGPIPE: scrittura su una pipe il cui lettore è uscito. La sua azione predefinita, terminare, è il motivo per cui yes | head finisce e per cui i server devono ignorarlo o gestire gli errori di scrittura.
  • SIGCHLD: un figlio è uscito; i padri raccolgono i figli con wait(), e un padre che non lo fa lascia zombie.
  • SIGWINCH: il terminale è stato ridimensionato; editor e multiplexer ridisegnano.

Inviare segnali

kill -TERM 1234        # per nome (o kill -15 1234)
kill -s USR1 $(pidof nginx)
pkill -HUP sshd        # per nome di processo
killall -9 runaway     # tutti i processi con quel nome
systemctl kill -s HUP myservice
docker kill --signal=SIGUSR1 container

I numeri 1–15 sono gli stessi su ogni Unix; oltre differiscono per architettura (SIGUSR1 è 10 su x86 e 30 su SPARC/MIPS), ed è per questo che gli script dovrebbero usare i nomi.

Domande

Che differenza c’è tra SIGTERM e SIGKILL?

SIGTERM chiede al processo di uscire e può essere gestito; SIGKILL lo termina immediatamente e non può essere catturato. Prova sempre prima TERM; KILL è per i processi bloccati.

Cos’è il segnale 11 / SIGSEGV?

Un segmentation fault: il programma ha letto o scritto memoria che non gli appartiene, di solito un puntatore nullo o pendente in codice C/C++ o un bug in un’estensione nativa. La shell riporta il codice di uscita 139.

Perché il mio processo è uscito con 137 se nessuno ha eseguito kill -9?

L’ha fatto il kernel: l’out-of-memory killer invia SIGKILL al processo più grande quando la memoria finisce, e i runtime dei container fanno lo stesso quando viene raggiunto un limite di memoria. Controlla dmesg o il flag OOMKilled del container.

Posso ignorare SIGINT così Ctrl-C non ferma il mio script?

Sì: trap "" INT in bash, o signal.signal(SIGINT, SIG_IGN) in Python. Di solito è meglio catturarlo e fare pulizia prima di uscire, così l’utente può comunque fermare lo script.