A frozen script, a runaway worker eating all CPU, a process holding a port you need — sometimes you have to stop a process by hand. Linux does this with signals, and choosing the right one matters.
First: is it a service?
If the process belongs to a systemd service (Nginx, MySQL, PHP-FPM, your app), stop or restart it through systemd rather than killing it:
sudo systemctl restart php8.3-fpm
sudo systemctl stop myapp
Otherwise systemd may simply restart it, or you’ll leave the service in a confusing state. Check with systemctl status <PID>, which shows the owning unit. For Docker containers use docker stop, for PM2 apps pm2 stop.
Find the PID
pgrep -a python
ps aux | grep '[m]yscript'
sudo ss -tlnp | grep ':8080' # process listening on a port
See ps command for more ways.
kill: send a signal to a PID
kill 1234 # SIGTERM (15): ask the process to exit cleanly
kill -9 1234 # SIGKILL (9): terminate immediately
kill -HUP 1234 # SIGHUP (1): many daemons reload their config
SIGTERM first, SIGKILL last
- SIGTERM lets the program clean up: finish writing files, close database connections, remove lock files. Well-behaved programs exit within seconds.
- SIGKILL can’t be caught or ignored — the kernel removes the process instantly. Nothing gets cleaned up: temporary files remain, data in buffers may be lost, child processes may be orphaned.
Good practice:
kill 1234
sleep 5
kill -0 1234 2>/dev/null && kill -9 1234
(kill -0 sends nothing; it only checks whether the process still exists.)
Common signals
| Signal | Number | Typical use |
|---|---|---|
SIGHUP |
1 | Reload configuration (Nginx, many daemons) |
SIGINT |
2 | Same as pressing Ctrl+C |
SIGKILL |
9 | Force kill |
SIGTERM |
15 | Polite termination (default) |
SIGSTOP |
19 | Pause (can’t be ignored) |
SIGCONT |
18 | Resume a paused process |
SIGUSR1/2 |
10/12 | App-specific (e.g. reopen logs) |
List all: kill -l.
pkill and killall: by name
pkill -f "python worker.py" # match against the full command line
pkill -u alice # all processes of a user
pkill -9 -x node # exact process name, SIGKILL
killall php # all processes named exactly "php"
killall -i php # ask before each
Preview what pkill would match with pgrep and the same options first:
pgrep -af "python worker.py"
pkill -f matches substrings of the full command — pkill -f python would also kill unrelated Python processes, including system tools. Be specific.
Free a port
“Address already in use” when starting a service? Find and stop whatever holds the port:
sudo ss -tlnp 'sport = :3000'
sudo fuser -k 3000/tcp # kill whatever uses TCP port 3000 (SIGKILL by default)
sudo fuser -k -TERM 3000/tcp # same, with SIGTERM
Kill a process tree
Killing a parent doesn’t necessarily kill its children. To stop a whole group:
kill -- -$(ps -o pgid= -p 1234 | tr -d ' ') # signal the entire process group
pkill -P 1234 # direct children of PID 1234
systemd handles this for services automatically (it kills the whole cgroup).
When kill -9 doesn’t work
Zombies (Z) are already dead; they’re just an entry waiting for the parent to read the exit status. You can’t kill them — kill or restart the parent instead. See zombie processes.
Uninterruptible sleep (D) — the process is stuck inside the kernel, usually waiting for storage (a hung NFS mount, a failing disk). Signals are delivered only when it returns. Fix the underlying I/O problem (remount, restore the network share); in the worst case, reboot.
Pause instead of kill
kill -STOP 1234 # freeze a CPU hog temporarily
kill -CONT 1234 # resume
Or lower its priority so it stops competing: renice +19 -p 1234. See process priority with nice.
Who killed my process?
If something died unexpectedly:
sudo journalctl -k | grep -i "killed process" # the OOM killer?
sudo journalctl -u myapp -n 50 # the service's own log
The out-of-memory killer is the most common “mystery killer” on small servers — see the Linux OOM killer.
Quick reference
| Task | Command |
|---|---|
| Polite stop | kill PID |
| Force stop | kill -9 PID |
| Reload config | kill -HUP PID |
| By name | pkill -x NAME |
| By command line | pkill -f "pattern" |
| By user | pkill -u USER |
| Port holder | fuser -k 8080/tcp |
| Check if alive | kill -0 PID |
Related: top and htop, where you can also kill processes interactively.