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.

  • Linux
  • Processes
  • Command Line