Managing Processes
Every running program on a Linux server is a process — an instance of a program that the kernel (the core of the operating system) is actively executing. Each process has a unique number called a PID (Process ID) that you use to inspect or control it. As a DevOps engineer you will constantly ask “what is running?”, “why is the server slow?”, and “how do I stop this stuck program?” — and the answer always comes down to managing processes. This page shows you how to list, watch, prioritise, and kill processes on Ubuntu.
What a process is
When you run a command like nginx or python app.py, the kernel creates a process for it. That process has a PID, an owner (the user that started it), a parent (the process that launched it), and a state (running, sleeping, or stopped). Processes can start other processes — for example systemd (Ubuntu’s service manager, PID 1) starts almost everything else when the machine boots.
You mostly interact with processes in two situations: inspecting them (to understand load or find a misbehaving program) and controlling them (to stop, pause, or reprioritise them). We’ll cover both.
Listing processes with ps
ps (process status) prints a snapshot of processes at the moment you run it. The most common form is ps aux, which shows all processes from all users with usage details.
ps aux
Output:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.4 168140 12996 ? Ss 09:01 0:02 /sbin/init
www-data 1423 0.1 1.2 145820 49180 ? S 09:05 0:11 nginx: worker process
deploy 2204 78.3 3.1 998120 12840 ? Rl 10:32 4:55 python app.py
Key columns: USER (owner), PID, %CPU and %MEM (share of CPU and memory used), STAT (state — R running, S sleeping, Z zombie), and COMMAND. Use it when you need a one-time list you can pipe into grep or save to a file.
To find one program, pipe ps aux into grep:
ps aux | grep nginx
When to use this: quick, scriptable snapshots. For watching live, use top or htop instead.
Watching live with top
top is built into every Ubuntu system and refreshes every few seconds, sorted by CPU usage by default. It’s the fastest way to spot a process eating the server.
top
While top runs, useful keys are: P (sort by CPU), M (sort by memory), k (kill a process — it asks for the PID), and q (quit). Press 1 to see each CPU core separately.
A friendlier view with htop
htop is an interactive, colourful version of top with mouse support, scrolling, and easy killing. It isn’t installed by default, so add it:
sudo apt update
sudo apt install -y htop
htop
In htop you can scroll with the arrow keys, press F6 to change the sort column, F3 to search by name, and F9 to send a signal (kill) to the highlighted process. It’s the tool most engineers reach for when troubleshooting interactively.
| Tool | Installed by default? | Best for |
|---|---|---|
ps aux | Yes | One-time snapshots, scripting |
top | Yes | Live monitoring on a bare server |
htop | No (apt install htop) | Comfortable interactive troubleshooting |
Finding a process that’s hogging CPU
Suppose the server feels slow. List the top CPU users in one line:
ps aux --sort=-%cpu | head -n 5
Output:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
deploy 2204 78.3 3.1 998120 12840 ? Rl 10:32 4:55 python app.py
www-data 1423 0.1 1.2 145820 49180 ? S 09:05 0:11 nginx: worker
root 1 0.0 0.4 168140 12996 ? Ss 09:01 0:02 /sbin/init
The --sort=-%cpu flag sorts highest-first. Here PID 2204 (python app.py) is using 78% of a CPU — the likely culprit. Swap %cpu for %mem to hunt down memory hogs instead.
Background jobs: jobs, bg, and fg
When you run a long command in a terminal, it runs in the foreground and blocks your prompt. You can pause and background it without killing it:
- Press Ctrl+Z to suspend (pause) the foreground command.
- Run
bgto resume it in the background so your prompt is free. - Run
fgto pull it back to the foreground. - Run
jobsto list jobs started from this shell.
sleep 300
# press Ctrl+Z to suspend
bg
jobs
Output:
[1]+ Running sleep 300 &
When to use this: for tasks tied to your current terminal session. For anything that must survive logout, use a systemd service instead — background jobs die when the shell closes.
Killing processes and signals
To stop a process you send it a signal — a message asking it to do something. The two you’ll use most are TERM (terminate gracefully) and KILL (force-stop immediately).
| Signal | Number | Meaning | Can the process ignore it? |
|---|---|---|---|
SIGTERM | 15 | Politely ask to shut down (default) | Yes — it can clean up first |
SIGKILL | 9 | Force-kill immediately | No — kernel ends it instantly |
SIGHUP | 1 | Hang up — often means “reload config” | Yes |
kill — by PID
kill sends a signal to a specific PID. Always try TERM first so the program can shut down cleanly (flush data, close files):
kill 2204 # sends SIGTERM (graceful)
kill -9 2204 # sends SIGKILL (force) — only if TERM fails
Reach for
kill -9only as a last resort. SIGKILL gives the process no chance to save data or release locks, which can corrupt files or leave stale lock files behind. Try plainkillfirst and wait a few seconds.
killall and pkill — by name
When you don’t know the PID, target the process by name:
killall nginx # kill every process literally named "nginx"
pkill -f "python app.py" # match against the full command line
killall matches the exact program name; pkill -f matches a pattern anywhere in the command line, which is handy for scripts. Both accept -9 to force-kill.
Changing priority with nice and renice
Every process has a niceness value from -20 (highest priority) to 19 (lowest). A “nicer” (higher) number means the process yields CPU to others — useful for background jobs like backups that shouldn’t slow down your app.
Start a command with lower priority:
nice -n 10 tar -czf backup.tar.gz /var/www
Change the priority of a process already running (needs sudo to raise priority):
sudo renice -n 5 -p 2204
Output:
2204 (process ID) old priority 0, new priority 5
When to use this: to keep heavy batch work from starving interactive or production processes — not to “speed up” a program, since lowering niceness only helps when the CPU is contended.
Best practices
- Use
htop(ortop) to diagnose live load; useps aux --sort=-%cpufor a quick scriptable snapshot. - Always send
SIGTERMfirst; only useSIGKILL(-9) when a process ignores a graceful stop. - Prefer
pkill -fover guessing PIDs when targeting a known command line, but double-check the match — a loose pattern can kill the wrong process. - For anything that must keep running after you log out, create a systemd service instead of backgrounding a shell job.
- Use
nice/reniceto keep backups and batch jobs from starving production processes. - Watch out for
Z(zombie) states inps— they usually point to a parent process that isn’t cleaning up its children correctly.