Chapter 8: Processes

Signals and ending processes

A signal is a short message the kernel or another process sends to a process: "stop", "reload", "pause", "die now". kill is the tool to send them, and despite its name it does much more than kill. Knowing which signal to send, and in what order, is the difference between a clean shutdown and lost data.

What signals are

Every signal has a number and a name. A process may catch most of them and decide what to do: a well-written program catches SIGTERM, saves its work, removes its temporary files and exits. Two signals cannot be caught or ignored: SIGKILL and SIGSTOP. They are handled by the kernel itself.

Common signals: Select a signal to see when to use it.

kill -l lists them all. Plain kill PID sends 15, SIGTERM, which is the polite request.

Sending signals

CommandSends to
kill PIDOne process, SIGTERM
kill -9 PID or kill -KILL PIDOne process, SIGKILL
kill -STOP PID, kill -CONT PIDPause and resume
kill %NA job of your shell
pkill NAMEEvery process whose name matches
pkill -u USEREvery process owned by the user
killall NAMEEvery process with exactly that name
pgrep -a NAMEOnly list the matches (the safe preview)

You may signal your own processes; root may signal anything.

[root@servera ~]# su - bob -c 'nohup sleep 900 >/dev/null 2>&1 & nohup sleep 901 >/dev/null 2>&1 &'
[root@servera ~]# pgrep -u bob -a sleep
4986 sleep 900
4987 sleep 901
[root@servera ~]# pkill -u bob sleep
[root@servera ~]# pgrep -u bob -a sleep

Always preview with pgrep first. pkill matches part of a name by default, so pkill java also ends javascript-lint unless you add -x for an exact match. pkill -u bob with no name ends everything bob runs, including his login shell, which logs him out.

Ask first, insist later

Step through the safe order:

Ending a stuck process: Step through the safe order of escalation.

The reason is what happens to the program. With a polite SIGTERM, a script like this tidies up:

[student@servera ~]$ cat cleanup.sh
#!/bin/bash
trap 'echo "cleaning up"; rm -f /tmp/work.lock; exit 0' TERM
touch /tmp/work.lock
while true; do sleep 1; done
[student@servera ~]$ ./cleanup.sh &
[1] 4921
[student@servera ~]$ kill %1
[student@servera ~]$ Terminated
cleaning up
[student@servera ~]$ ls /tmp/work.lock
ls: cannot access '/tmp/work.lock': No such file or directory

With SIGKILL the program never gets to run its cleanup, so the lock file stays behind:

[student@servera ~]$ ./cleanup.sh &
[1] 4928
[student@servera ~]$ kill -9 %1
[student@servera ~]$ ls /tmp/work.lock
/tmp/work.lock

This is exactly why SIGKILL is a last resort: databases lose buffered writes, editors lose unsaved files, and locks and sockets stay on disk.

When kill does not work

Check your understanding