Stopping a stuck program correctly, without losing data, depends on picking the right signal.
A signal is a small asynchronous notification the kernel delivers to a process. Programs can handle most signals (run cleanup code), ignore them, or accept the default action, usually termination. The ones to know:
SIGTERM(15): "please terminate". The default ofkill; well-behaved programs save state and exit. systemd and Docker send it first when stopping.SIGINT(2): what Ctrl-C sends to the foreground process.SIGKILL(9): terminates immediately. It cannot be caught, so no cleanup happens: temporary files, locks and half-written data may remain. Use it only when SIGTERM fails.SIGHUP(1): originally "terminal hung up"; many daemons (nginx, sshd) reload their configuration on it.SIGSTOP/SIGCONT: pause and resume (Ctrl-Z sends the catchableSIGTSTP).SIGCHLD,SIGPIPE,SIGSEGVhappen automatically.
Send them with kill -SIGNAL PID (kill -TERM 1234, kill -9 1234), by name with pkill pattern or killall name, and list them with kill -l. You can only signal your own processes unless you are root.
The usual escalation: kill PID, wait a few seconds, check with ps, and only then kill -9. A process in state D or a zombie will not die from signals at all: fix the I/O problem or the parent.
Example
sleep 600 &
pid=$!
kill "$pid" # SIGTERM (15): please exit
sleep 600 & pid=$!
kill -STOP "$pid"
ps -o pid,stat,cmd -p "$pid" # STAT T = stopped
kill -CONT "$pid" # resume
kill -9 "$pid" # SIGKILL: no cleanup, last resort
kill -l | head -n 2 # signal numbers and names
pkill -f 'python worker.py' # match against full command lines
sudo kill -HUP "$(pgrep -o nginx)" # nginx reloads its config on SIGHUP
sudo systemctl kill -s HUP nginx # same, for a systemd serviceRemember
- kill sends SIGTERM by default: ask first
- SIGKILL (9) cannot be handled; use it last
- SIGHUP often means 'reload configuration'
Watch out for
- Reaching for kill -9 first, losing the program's chance to flush data and remove lock files.