Linux Process Management Cheat Sheet
ps aux --sort=-%cpu | head # top CPU users
pgrep -a firefox # PIDs and command lines matching a name
kill 12345 # ask PID 12345 to exit (SIGTERM)
pkill -f 'python app.py' # same, matching the full command line
top # live view (press P for CPU, M for memory, q to quit)
nohup ./job.sh > job.log 2>&1 & # run in the background, survives logout
Every running program is a process with a numeric PID, an owner and a parent. Most tools here come from procps-ng (ps, top, pgrep, pkill, kill) and are installed everywhere. htop and btop are optional extras in every distro's repositories. Processes started by systemd services should be managed with systemctl, not killed by hand, or systemd will just restart them.
Listing processes with ps
| Command | What it does |
|---|---|
ps aux | Every process, BSD style: user, PID, %CPU, %MEM, state, command |
ps -ef | Every process, System V style, including the parent PID (PPID) |
ps -ef --forest | Show the parent/child tree |
pstree -p | Compact process tree with PIDs |
ps aux --sort=-%mem | head | Biggest memory users first |
ps -u alice | Processes owned by a user |
ps -p 1234 -o pid,ppid,user,stat,etime,cmd | Chosen columns for one PID (etime = running time) |
ps -C nginx -o pid,rss,cmd | Select by exact command name |
ps -eLf | Show threads |
ps -eo pid,stat,cmd | awk '$2 ~ /^[DZ]/' | Processes stuck in D (I/O wait) or Z (zombie) state |
STAT letters: R running, S sleeping, D uninterruptible I/O wait, T stopped, Z zombie. Extra flags: < high priority, N low priority, s session leader, + foreground.
Finding processes
| Command | What it does |
|---|---|
pgrep nginx | PIDs whose name contains nginx |
pgrep -a nginx | PIDs with full command lines |
pgrep -f 'manage.py runserver' | Match against the whole command line |
pgrep -u www-data -l | Processes of one user, with names |
pidof sshd | PIDs of an exact program name |
sudo ss -ltnp | Which process listens on which TCP port |
sudo lsof -i :443 | Processes using a port |
sudo fuser -v /mnt/usb | Processes using a file or mount point |
sudo lsof -p 1234 | Files, sockets and libraries opened by a PID |
systemctl status 1234 | Which systemd unit (service, scope) a PID belongs to |
Live monitoring: top and htop
| Command or key | What it does |
|---|---|
top | Live process list, refreshed every 3 seconds |
top -o %MEM | Start sorted by memory |
top -u alice | Only one user's processes |
top -b -n 1 | head -20 | One snapshot in batch mode (for scripts and logs) |
top keys: P M T | Sort by CPU, memory, time |
top keys: 1 c H | Per-CPU lines, full command, show threads |
top keys: k r | Kill or renice a PID from inside top |
htop | Friendlier top: scroll, mouse, tree view (F5), search (F3), filter (F4), kill (F9) |
btop | Full-screen dashboard with CPU, memory, disk and network graphs |
systemd-cgtop | CPU and memory per service or user slice |
uptime / cat /proc/loadavg | Load averages over 1, 5 and 15 minutes |
free -h | RAM and swap usage (look at the available column) |
Tracking down something that keeps the fans spinning? Follow the high CPU and memory usage guide.
Signals: kill, pkill, killall
| Command | What it does |
|---|---|
kill PID | Send SIGTERM (15): polite request to exit |
kill -9 PID (kill -KILL PID) | SIGKILL: immediate, cannot be caught. Last resort. |
kill -HUP PID | SIGHUP: many daemons reload their configuration |
kill -STOP PID / kill -CONT PID | Pause and resume a process |
kill -INT PID | SIGINT: same as pressing Ctrl+C |
kill -l | List all signal names and numbers |
pkill firefox | SIGTERM to every process whose name matches |
pkill -f 'node server.js' | Match the full command line |
pkill -u alice | Every process of a user (logs them out) |
killall -w nginx | Kill by exact name and wait until they have exited |
kill -- -PGID | Signal a whole process group (negative number) |
sudo systemctl kill --signal=KILL app.service | Kill every process of a service |
Priority: nice, renice, ionice
| Command | What it does |
|---|---|
nice -n 19 tar czf backup.tgz /data | Start a command with the lowest CPU priority (range -20 to 19) |
renice -n 10 -p 1234 | Lower the priority of a running process |
sudo renice -n -5 -p 1234 | Raise priority (negative values need root) |
renice -n 15 -u alice | Change every process of a user |
ionice -c3 rsync -a src/ dst/ | Idle I/O class: only use the disk when nothing else needs it |
ionice -c2 -n7 -p 1234 | Lowest best-effort I/O priority for a running PID |
taskset -c 0,1 cmd | Pin a command to CPUs 0 and 1 |
systemd-run --user -p CPUQuota=50% cmd | Hard cap a command at half of one CPU |
Jobs, background and logout
| Command or key | What it does |
|---|---|
cmd & | Start in the background of the current shell |
Ctrl+Z | Suspend the foreground job |
bg / bg %2 | Continue a suspended job in the background |
fg / fg %2 | Bring a job back to the foreground |
jobs -l | List this shell's jobs with PIDs |
kill %1 | Signal a job by job number |
nohup cmd > out.log 2>&1 & | Ignore the hangup signal so the command survives logout |
disown -h %1 | Detach an already running job from the shell |
setsid cmd | Run in a new session with no controlling terminal |
systemd-run --user --unit=myjob cmd | Run as a transient systemd unit (logs in the journal) |
wait | In a script, wait for background jobs to finish |
For interactive work you want to come back to, tmux is easier than nohup.
Common recipes
Stop a frozen program gracefully, then forcefully if it ignores you:
pkill -f myapp; sleep 5; pgrep -f myapp && pkill -9 -f myapp
Free a port that something is still holding (see Address already in use):
sudo ss -ltnp 'sport = :8080'
sudo kill "$(sudo lsof -t -i :8080)"
Top 10 processes by real memory (RSS), in MiB:
ps -eo rss,pid,comm --sort=-rss | head -11 | awk 'NR==1{print;next}{printf "%7.1f %s %s\n",$1/1024,$2,$3}'
Find out why a process was killed unexpectedly (often the OOM killer, see Out of memory: Killed process):
journalctl -k -b | grep -iE 'killed process|out of memory'
Find the parent of a zombie and restart it:
ps -eo pid,ppid,stat,cmd | awk '$3 ~ /Z/'
ps -p PARENT_PID -o pid,cmd
Run a heavy job without hurting interactive use:
nice -n 19 ionice -c3 make -j"$(nproc)"
Gotchas
- Do not reach for
kill -9first. SIGKILL gives the program no chance to save state or remove lock files, which is a common cause of "database is locked" and dpkg lock errors afterwards. pkillmatches substrings.pkill shalso killsbash,sshandzsh. Preview withpgrep -a, or anchor:pkill -x sh.- Process names are cut to 15 characters for
pgrepandpkillwithout-f. - Services come back. Killing a process that belongs to a unit with
Restart=starts a new one. Usesystemctl stop. - Load average is not CPU percent. It counts processes running or waiting, including D-state I/O waits. A load of 8 on an 8-core machine is fully busy, not overloaded.
- %CPU over 100. In top and ps, 100% is one core. A multi-threaded program can show 400% on a 4-core machine. Press
Iin top to switch to Irix-off mode. - nohup still dies when systemd-logind kills user processes at logout (
KillUserProcesses=yes, set on some distros). tmux sessions are killed too in that case. Usesystemd-run --userplusloginctl enable-linger.
References: ps(1), top(1) and signal(7).
Frequently asked questions
How do I kill a process by name?
Use pkill name (matches part of the process name) or killall name (exact name). Check what would match first with pgrep -a name.
What is the difference between kill and kill -9?
Plain kill sends SIGTERM, which asks the program to exit and lets it clean up. kill -9 sends SIGKILL, which the kernel enforces immediately, so temporary files, locks and unsaved data can be left behind. Use -9 only when SIGTERM does not work.
How do I keep a command running after I log out?
Start it with nohup cmd &, or run it inside tmux or screen. For a long-running service, a systemd unit or systemd-run --user is the most reliable option.
Why can't I kill a process even with kill -9?
It is probably in state D (uninterruptible sleep), waiting on disk or network I/O such as a dead NFS mount, or it is a zombie (state Z) that is already dead and waiting for its parent. Fix the I/O or kill the parent.
How do I find which process uses a port?
Run sudo ss -ltnp 'sport = :8080' or sudo lsof -i :8080. The output includes the process name and PID.
Spotted a mistake or a command that no longer works? Send a correction — pages are re-checked when reports come in.