tallge

Reference / Signals and exit codes

Unix signals and exit codes

An exit code above 128 usually means a signal ended the process. This page lists the signals you meet in practice, the exit codes shells and tools use, and the order in which service managers send them.

Common signals

No.NameDefault actionUsually sent by
1SIGHUPterminatethe terminal closing; many daemons reload their configuration on it instead
2SIGINTterminateCtrl+C in the terminal
3SIGQUITcore dumpCtrl+\ in the terminal; the JVM prints a thread dump on it
4SIGILLcore dumpan illegal CPU instruction, for example a binary built for a newer CPU
6SIGABRTcore dumpthe program itself, through abort(), often after a failed assertion
7SIGBUScore dumpa bad memory access, such as reading a memory-mapped file that was truncated
8SIGFPEcore dumpan arithmetic error such as integer division by zero
9SIGKILLterminatekill -9, the out-of-memory killer, a service manager whose stop timeout ran out; cannot be caught, blocked or ignored
10SIGUSR1terminatean administrator or another program; the meaning is defined by the application
11SIGSEGVcore dumpan invalid memory reference: a crash in native code
12SIGUSR2terminateas SIGUSR1
13SIGPIPEterminatewriting to a pipe or socket whose reader has gone, as in producer | head
14SIGALRMterminatea timer set with alarm()
15SIGTERMterminatekill without options, systemd, Docker and Kubernetes when stopping: the polite request to exit
17SIGCHLDignorethe kernel, when a child process stops or exits
18SIGCONTcontinuefg, bg, kill -CONT
19SIGSTOPstopkill -STOP; cannot be caught, blocked or ignored
20SIGTSTPstopCtrl+Z in the terminal
24SIGXCPUcore dumpthe CPU time limit (ulimit -t) running out
25SIGXFSZcore dumpwriting past the file size limit (ulimit -f)
28SIGWINCHignorethe terminal window changing size

The numbers are those of Linux on x86 and ARM, the same on most other architectures. Alpha, SPARC and MIPS number several signals differently, so scripts should use names: kill -TERM, not kill -15. "Core dump" means the process terminates and the kernel writes a core file if the core size limit allows it (ulimit -c).

Sending and handling signals

TaskCommand
Ask a process to exitkill PID
Send a specific signal by namekill -HUP PID
Check that a process exists and you may signal itkill -0 PID
Signal every process named exactly apppkill -TERM -x app
Signal a whole process groupkill -TERM -- -PGID
Signal a service and all its processes (systemd)sudo systemctl kill -s HUP app.service
List signal names and numberskill -l
Clean up when a script exits or is interruptedtrap 'rm -f "$tmp"' EXIT
Give a command 30 seconds, then TERM, then KILL 5 seconds latertimeout -k 5 30 ./job.sh

Send SIGTERM first and SIGKILL only if the process does not exit. A process killed with SIGKILL gets no chance to flush buffers, remove lock files or finish a transaction.

Exit codes

CodeMeaning
0success
1general failure; most programs use it for any error
2incorrect usage of a shell builtin in bash; many programs also use it for bad arguments, and grep for errors (1 means "no match")
124timeout stopped the command because the time ran out
125timeout itself failed
126the command was found but could not be executed: no execute permission, or not a valid executable
127command not found: a typo, or a PATH that does not include it, as under cron
128 + nthe command was ended by signal n
130128 + 2: SIGINT, Ctrl+C
137128 + 9: SIGKILL; often the out-of-memory killer, or a stop timeout that ran out
143128 + 15: SIGTERM; a normal stop request that the program did not handle
255exit -1 and other out-of-range values; ssh also returns 255 for its own errors

An exit status is 8 bits wide. exit 256 gives 0 and exit -1 gives 255, so never use a count of errors as the exit status. The 128 + n values are what the shell reports; the process itself did not exit. Python's subprocess reports the same case as a negative return code, -15 for SIGTERM.

./job.sh; echo $?          # status of the last command
false | true; echo $?       # 0: a pipeline returns the last command's status
set -o pipefail             # make a pipeline fail if any command in it fails

sysexits.h codes

Some programs, mail software in particular, use the BSD codes from sysexits.h. They are a convention, not a requirement of POSIX.

CodeNameMeaning
64EX_USAGEthe command was used incorrectly
65EX_DATAERRthe input data was incorrect
66EX_NOINPUTan input file did not exist or was not readable
67EX_NOUSERthe user does not exist
68EX_NOHOSTthe host does not exist
69EX_UNAVAILABLEa service is unavailable
70EX_SOFTWAREinternal software error
71EX_OSERRoperating system error, such as a failed fork
72EX_OSFILEa system file is missing or invalid
73EX_CANTCREATan output file cannot be created
74EX_IOERRinput or output error
75EX_TEMPFAILtemporary failure; trying again later may work
76EX_PROTOCOLthe remote side broke the protocol
77EX_NOPERMpermission denied
78EX_CONFIGconfiguration error

How services are stopped

ManagerFirstThenWaits by default
systemdKillSignal=, default SIGTERMSIGKILL to what is leftTimeoutStopSec=, 90 s unless changed
Docker (docker stop)SIGTERM, or the image’s STOPSIGNALSIGKILL10 s for Linux containers
KubernetesSIGTERM (after any preStop hook)SIGKILLterminationGracePeriodSeconds, 30 s
timeoutSIGTERM, or the signal from -sSIGKILL only with -kthe duration you give

A process that takes the full grace period to stop is usually ignoring SIGTERM. In a container this happens often for a reason that is easy to miss: the first process in a PID namespace receives only the signals it has installed a handler for, so a program without a SIGTERM handler running as PID 1 ignores the default action and waits to be killed. Run it under a small init process, such as docker run --init, or handle SIGTERM in the program.

Sources