The machine is slow. The fan is spinning, something is eating your CPU or your memory, and you have no idea what. Or a program has hung and will not close, and you want to make it stop without rebooting the whole computer. This guide is the toolkit for exactly that: seeing what is running and controlling it.
Everything that runs on a Linux system is a process. Your web browser is a process (often dozens of them), the music player is a process, the background services that keep the machine working are processes. Learning to list them, read what they are doing, and politely (or forcibly) stop them is one of the most useful skills on the command line — and every tool here is free and open source, one apt/pacman/dnf away. Nothing on this page is paid, proprietary, or cloud.
This is a companion to the logs guide (journalctl, /var/log, dmesg): when a process misbehaves, the tools here tell you what is wrong right now, and the logs tell you why it happened. You do not need to read top to bottom — jump to your situation with the table of contents.
What a process actually is
A process is simply a running program. The moment you launch something, the kernel gives it a PID — a Process ID, a unique number — and tracks it until it exits. Almost everything you do below comes down to finding the right PID and acting on it.
A few ideas that make the rest of the guide click:
- PID — the process's own ID number.
1is special: it is the very first process the kernel starts (systemdon most distributions), and every other process descends from it. - PPID — the Parent PID. Every process is started by another one, so they form a family tree. Your shell starts a command; that command is the shell's child. Kill a parent and its children usually go too.
- State — what the process is doing right now. The common ones are running (using the CPU), sleeping (waiting for something — input, a timer, the disk; this is the normal resting state, not a problem), and zombie. A zombie is a process that has finished but whose parent has not yet collected its exit status — it holds no memory or CPU, it is just a leftover entry in the table. A handful are harmless; they vanish when the parent reaps them or itself exits.
- Foreground vs background — a foreground process owns your terminal until it finishes (you wait at the prompt). A background process runs while you keep using the same terminal. The job-control section below is all about moving between the two.
To see the family tree at a glance, pstree draws it (install psmisc if missing), and ps can show it too:
# draw the process tree, with PIDs
pstree -p
# the same idea from ps, as an indented forest
ps -e --forest
Listing processes with ps
ps (part of procps-ng, free software, GPL; already installed everywhere) prints a snapshot of what is running. It has two old command styles that both survive; you will see both, so know both. The BSD style needs no dashes:
# every process on the system, with resource usage (the one to memorise)
ps aux
The traditional UNIX style uses dashes and prints the same idea in a slightly different layout:
# every process, full detail, including the parent PID column
ps -ef
The output of ps aux has one process per line. The columns worth knowing:
| Column | What it means |
|---|---|
| USER | Who owns (started) the process. |
| PID | The process ID — the number you act on. |
| %CPU | Share of one CPU core it is using right now. |
| %MEM | Share of physical RAM it is using. |
| RSS | Resident Set Size — the real RAM it holds, in kilobytes. The honest memory number. |
| STAT | State code: R running, S sleeping, D uninterruptible sleep (usually waiting on disk), Z zombie, T stopped. |
| TIME | Total CPU time used so far (not wall-clock time). |
| COMMAND | The command line that started it. |
That is a lot of lines. The real trick is to sort it and keep only the top few. To find what is eating your CPU or RAM:
# the 10 heaviest CPU users
ps aux --sort=-%cpu | head
# the 10 heaviest memory users
ps aux --sort=-%mem | head
The leading - in --sort=-%cpu means "biggest first". This single line answers "what is eating my CPU?" better than anything else.
Finding a process by name: pgrep and pidof
When you know the program's name but not its PID, you do not need to eyeball ps. pgrep (also from procps-ng) searches for you:
# print the PIDs of every firefox process
pgrep firefox
# add the matching command line so you can be sure it is the right one
pgrep -a firefox
# match against the WHOLE command line, not just the program name
pgrep -f 'node server.js'
pidof does a simpler version of the same job and is handy in scripts:
# just the PID(s) of a named program
pidof sshd
Live monitors: top, htop, btop
ps is a still photo. To watch the system move — see who climbs to the top of the CPU list, who is leaking memory — you want a live monitor that refreshes every couple of seconds.
top — always there
top (procps-ng, free software, GPL) is installed on every Linux system, so it is the one you can always count on. Run it with no arguments:
top
The top few lines summarise the whole machine (load average, CPU%, memory); below that is the live, sorted process list. It is interactive — press these keys while it is running:
P— sort by CPU usage (the default).M— sort by memory usage.k— kill a process: it asks for the PID, then the signal (just press Enter for the polite default).r— renice (change priority — see below).1— toggle a per-core CPU breakdown.q— quit.
htop — the friendly one
htop (free software, GPL) is what most people install the first day on a new machine. It does everything top does but is far friendlier: a colour bar per CPU core, a memory gauge, a scrollable list you can navigate with the arrow keys and the mouse, and function-key buttons along the bottom for searching, filtering, sorting, and killing — no codes to memorise.
# Debian / Mint / Ubuntu
sudo apt install htop
# Arch / Manjaro
sudo pacman -S htop
# Fedora
sudo dnf install htop
Inside htop: F6 chooses the sort column, F4 filters by name, F3 searches, and F9 kills the highlighted process (it shows a menu of signals). Press F2 to configure what it shows. It is the everyday tool.
btop — the pretty one
If you want something genuinely nice to look at — graphs of CPU, memory, network, and disk over time, all mouse-driven — btop (free software, Apache-2.0) is the modern favourite. Same job as htop, fancier presentation:
# Debian / Mint / Ubuntu (Debian 12+/recent Ubuntu)
sudo apt install btop
# Arch / Manjaro
sudo pacman -S btop
# Fedora
sudo dnf install btop
Run btop and click around, or press m, p, and the arrow keys. There is nothing you must learn here — it is the one to leave open on a second monitor.
Reading the numbers
The monitors throw a lot of figures at you. Here is what the important ones actually mean, so you can tell a busy-but-healthy machine from one in trouble.
Load average
The three numbers in uptime (and at the top of top) are the load average over the last 1, 5, and 15 minutes:
# show uptime and the three load-average figures
uptime
Load is, roughly, the average number of processes wanting the CPU at any moment. The key is to compare it to your core count: a load of 4.0 means the system is fully busy on a 4-core machine (fine), but badly overloaded on a 1-core machine. Find your core count with nproc. A rule of thumb: load below your core count = comfortable; well above it = work is queueing and things feel slow. The three figures show the trend — if the 1-minute number is far above the 15-minute one, load is climbing right now.
Memory: VIRT, RES, SHR, and why "free" looks low
Memory columns confuse everyone at first. In top/htop you see three numbers per process:
- VIRT (virtual) — every byte the process has asked for or mapped, including shared libraries and memory it never actually touches. It is almost always huge and mostly meaningless on its own — do not panic at a big VIRT.
- RES (resident, the same as RSS in
ps) — the real, physical RAM the process is using right now. This is the number that matters. - SHR (shared) — the part of RES that is shared with other processes (typically shared libraries), so it is counted against several processes at once.
For the whole machine, use free (procps-ng) with -h for human-readable units:
# show memory and swap in MB/GB
free -h
Tip: do not be alarmed when
free -hshows little memory "free" and a lot underbuff/cache. Linux deliberately uses spare RAM to cache files, which makes everything faster; that cache is released instantly the moment a program needs the memory. The number to watch is the available column — that is how much a new program can really get. High cache is healthy, not a leak.
If the available figure is tiny and swap is filling up, you are genuinely short on memory — that is when the machine starts thrashing and crawls.
vmstat: a one-line pulse
For a quick repeating heartbeat of the whole system, vmstat (procps-ng) prints one line per second:
# refresh every 1 second
vmstat 1
Watch three things: the r column (processes waiting to run — high means CPU-bound), the si/so columns (memory swapping in/out — anything but zero for long means memory pressure), and wa in the CPU group (time waiting on disk — high means you are I/O-bound, not CPU-bound). Press Ctrl-C to stop.
Signals: how you talk to a process
You do not "close" a process from the outside the way you click an X on a window — you send it a signal, a small numbered message the kernel delivers. The tool is kill (procps-ng), and despite the alarming name, most signals are perfectly gentle.
The two you will use constantly:
# SIGTERM (15) — the POLITE one: "please shut down cleanly".
# The process gets to save files, close connections, and exit tidily.
kill 4123
# this is identical — 15/TERM is the default signal
kill -15 4123
Most of the time that is all you need. Give it a couple of seconds. Only if the process ignores it do you escalate:
# SIGKILL (9) — the FORCE one. The kernel removes the process immediately.
kill -9 4123
Warning:
kill -9(SIGKILL) is a last resort, not a first move. The process gets no chance to clean up — unsaved data is lost, temp files and lock files are left behind, and a database killed this way can be left mid-write and corrupt. Always try plainkill(SIGTERM) first and give it a moment; reach for-9only when something is truly stuck.
Warning: double-check the PID before you send anything. Numbers shift constantly, and killing the wrong process — say, a database or your display server — can take down work or your whole desktop session. Confirm with
ps -p <pid> -o pid,user,cmd(or just look at the COMMAND inhtop) before you act.
The common signals
| Name | Number | What it does |
|---|---|---|
| SIGTERM | 15 | Polite "please shut down". Catchable, so the program can clean up. The default. |
| SIGKILL | 9 | Forced, immediate kill. Cannot be caught or ignored. No cleanup — last resort. |
| SIGHUP | 1 | Originally "terminal hung up". Many daemons treat it as "reload your config file". |
| SIGINT | 2 | Interrupt — exactly what Ctrl-C sends. A polite stop. |
| SIGSTOP | 19 | Pause (freeze) the process. Cannot be caught. It uses no CPU until resumed. |
| SIGCONT | 18 | Resume a process that was stopped with SIGSTOP. |
See the full list any time with kill -l. You name a signal by number (-9) or by name (-KILL or -SIGKILL) — they are equivalent.
Killing by name: killall and pkill
When you do not want to look up a PID, kill by name. killall (part of psmisc, free software, GPL) signals every process with an exact name:
# politely stop every process literally named "firefox"
killall firefox
# force it if that is ignored
killall -9 firefox
pkill (procps-ng, the sibling of pgrep) is more flexible — it matches the same way pgrep does, including against the whole command line with -f:
# match by program name
pkill chrome
# match anywhere in the full command line (use -f for scripts run by an interpreter)
pkill -f 'python my_script.py'
Warning: name-matching is broad —
pkill -f pythonwould hit every Python program on the system, not just yours. Always preview the targets withpgrep -ausing the same pattern before you run the matchingpkill. Verify, then kill.
Priorities: niceness and I/O
Sometimes you do not want to stop a process, just stop it from hogging the machine. Linux lets you set how nicely a process shares the CPU.
CPU priority: nice and renice
A process has a niceness from -20 (greediest, highest priority) to 19 (most generous, lowest priority). The name is literal: a "nicer" process yields the CPU more readily to others. Normal processes start at 0. Start a command with a chosen niceness using nice:
# run a heavy job at low priority so it does not slow your desktop
nice -n 10 tar -czf backup.tar.gz /home/you
Change the niceness of something already running with renice, by PID:
# make process 4123 lower priority (kinder to everything else)
renice -n 10 -p 4123
Tip: anyone can make a process nicer (raise the number, lower its priority). Only root can make one greedier (a negative number), so a normal user setting
nice -n -5needssudo. For background chores like backups and compiling,nice -n 10(or even19) keeps your machine responsive while they grind away.
Disk priority: ionice
Niceness only governs the CPU. A job that hammers the disk can make the system stutter even at low CPU priority. ionice (part of util-linux, free software, GPL) sets I/O priority the same way:
# run a backup in the "idle" I/O class: it only touches the disk when nothing else needs it
ionice -c 3 tar -czf backup.tar.gz /home/you
# or change a running process by PID
ionice -c 3 -p 4123
Pairing nice -n 19 ionice -c 3 <command> is the classic recipe for a background job that stays completely out of your way.
Job control: foreground, background, and beyond
This is how you juggle several things in one terminal. The shell calls each command you launch a job.
Start a command in the background by adding &, and it runs while you keep using the prompt:
# launch in the background; the shell prints a job number and PID
long-running-command &
Forgot the & and the command is now hogging your terminal? Press Ctrl-Z to suspend it (it pauses, frozen), then choose where it goes:
# list the shell's jobs (suspended and background)
jobs
# resume job 1 in the background (it keeps running, you get your prompt back)
bg %1
# bring job 1 back to the foreground (you wait on it again)
fg %1
One catch: a background job is still attached to your terminal, so it normally dies when you close that terminal or log out (it receives SIGHUP). Two ways to outlive the session:
# nohup: start a command immune to hangup, with output saved to nohup.out
nohup long-running-command &
# disown: detach a job you ALREADY started so the shell forgets it
long-running-command &
disown
Tip:
nohupanddisownwork, but for anything you genuinely care about — a long copy, a build, a download over SSH — run it inside tmux instead. A tmux session keeps running on the server even after you disconnect, and you reattach later to find it exactly as you left it, output and all. See the tmux guide for the twenty-minute version.
Who is using that file or port?
A different kind of question: not "what is busy?" but "what process is holding this file open, or listening on this port?" — the one that stops you unmounting a disk, or the mystery program squatting on port 8080.
lsof — list open files
lsof ("list open files"; free software under a permissive Purdue/BSD-style license — not GPL; usually already installed) shows which process has what open. On Linux nearly everything is a file, so this answers a lot:
# what is keeping /mnt/usb busy so it will not unmount?
sudo lsof /mnt/usb
# every file a given PID has open
sudo lsof -p 4123
# what is listening on, or connected to, network ports?
sudo lsof -i
# specifically, who holds TCP port 8080?
sudo lsof -i :8080
ss — sockets and ports
For network ports specifically, ss (part of iproute2, free software, GPL; the modern replacement for the old netstat) is faster and more direct:
# every listening TCP and UDP port, with the owning program and PID
sudo ss -tulpn
The letters: t TCP, u UDP, l listening only, p show the process, n numeric (do not slow down resolving names). This is the go-to for "what is listening on this machine?" — see the networking-basics guide for more on ss and friends.
iotop — who is hammering the disk
When the disk light is solid and the machine is sluggish but the CPU looks idle, something is doing heavy I/O. iotop (free software, GPL) is "top for disk", showing read/write rates per process:
# or pacman -S / dnf install iotop
sudo apt install iotop
# show only processes actually doing I/O right now
sudo iotop -o
It needs root because per-process I/O accounting is privileged. Sort with the arrow keys; it instantly answers "what is thrashing my disk?"
Processes vs services: a bridge to systemd
Everything above treats a process as a lone thing you start and stop by hand. But the long-lived programs that keep your system working — the SSH server, the print spooler, the web server — are also just processes. The difference is that they are supervised: started, watched, restarted-on-crash, and logged by the init system, which on almost every modern distribution is systemd.
So while you could hunt down a service's PID and kill it, that is the wrong tool — systemd would often just start it back up. For services, ask systemd instead:
# is the SSH service running? (shows its main PID, memory, recent log lines)
systemctl status ssh
# stop / start / restart it properly (systemd handles the signals for you)
sudo systemctl restart ssh
Think of it as two layers: the raw ps/kill/htop tools here for any process and for one-off programs you launched yourself; systemctl for the managed services on top. For the full tour of units, enabling services at boot, and reading their logs, see the systemd guide and the logs guide.
Quick reference
ps aux --sort=-%cpu | head— top CPU users (swap%cpufor%memfor memory).pgrep -a name/pidof name— find a process's PID by name.top— always-available live monitor (PCPU,Mmemory,kkill,qquit).htop/btop— friendlier live monitors (install once, never go back).uptime+nproc— load average vs core count;free -h— memory (watch available);vmstat 1— live pulse.kill <pid>— polite stop (SIGTERM).kill -9 <pid>— force (SIGKILL, last resort).killall name/pkill -f pattern— kill by name (preview withpgrep -afirst).nice -n 10 cmd/renice -n 10 -p <pid>— CPU priority;ionice -c 3 cmd— disk priority.cmd &,Ctrl-Z,bg/fg,jobs,nohup,disown— job control (or run it in tmux).sudo lsof /path/sudo lsof -i :PORT— who holds a file or port.sudo ss -tulpn— listening ports + owning process.sudo iotop -o— who is hammering the disk.systemctl status <svc>— for managed services, ask systemd, do notkillthem.
Tools used in this guide (all free and open source)
Every program named above is free and open source. Here is each one with its project page and license — nothing on this page is paid, proprietary, or cloud.