What's Running: ps, top and htop
Every running program is a process with a number, its PID: ps lists the ones in your terminal, ps aux lists every one on the computer, ps aux --sort=-%cpu puts the busiest first, and top and htop show the same list live.
Apprentice · Unix · Linux · Updated
After this lesson you can
- List running processes with ps and ps aux, and read a line's PID, %CPU, %MEM and command
- Find the process using the most CPU or memory with ps aux --sort, top or htop
Key takeaways
- A process is a program while it runs. Each one gets a number, its PID, and commands that stop or watch a process name it by that number.
- ps lists the processes in this terminal. ps aux lists every process on the computer, with its user, PID, %CPU, %MEM and command.
- A script shows up as bash followed by the script's name, because bash is the program running it.
- ps aux --sort=-%cpu | head -n 2 shows the busiest process. 100% CPU is one whole processor core.
- top and htop show the list live, busiest first, until you press q.
Your laptop was fine an hour ago. Now the fan is roaring, the battery is draining, and every click takes a second to answer. Something is working the computer hard, and you want to know what. On a desktop you'd open Task Manager, Activity Monitor or System Monitor. On a server, a Raspberry Pi or a cloud machine there's no window to open, and the same question is answered with ps and top. A developer asks it when a test run never finishes; an administrator asks it every time a server slows down.
Every running program is a process
A recipe in a cookbook doesn't cook anything; a cook following it does. Programs work the same way. The file on the disk is the recipe, and each time it runs, the computer starts a process: the program at work. Two cooks can follow the same recipe at once, and two copies of a program are two processes. Like tickets at a deli counter, each process gets a number, its process ID, or PID.
ps (for process status) lists the processes running in your terminal:
ps
PID TTY TIME CMD
1722 pts/4 00:00:00 bash
1802 pts/4 00:00:00 ps
Two processes: bash, the shell reading your commands, and ps itself, which was running while it made the list. TTY names the terminal they belong to (pts/4 is a terminal window, read "pseudo-terminal 4"), and TIME is how much work the processor has done for each so far. Your numbers will be different: PIDs are handed out as programs start.
Every process on the computer: ps aux
Make a practice folder with three small programs that misbehave on purpose. runaway.sh is stuck in a loop, counting as fast as it can; the other two are for the next lessons:
mkdir -p ~/terminal-practice/processes
cd ~/terminal-practice/processes
printf '%s\n' '#!/usr/bin/env bash' '# runaway.sh: stuck in a loop, counting as fast as it can, forever.' 'n=0' 'while true; do n=$((n + 1)); done' > runaway.sh
printf '%s\n' '#!/usr/bin/env bash' '# alarm.sh: beeps once a second until something stops it.' 'while true; do' ' echo "BEEP"' ' sleep 1' 'done' > alarm.sh
printf '%s\n' '#!/usr/bin/env bash' '# export-video.sh: pretends to export a video, one frame a second.' 'for frame in {1..600}; do' ' echo "Exported frame $frame of 600"' ' sleep 1' 'done' > export-video.sh
chmod +x runaway.sh alarm.sh export-video.sh
Open a second terminal window or tab (on Windows, a second Ubuntu tab), and start the runaway there:
cd ~/terminal-practice/processes
./runaway.sh
Nothing prints: it's busy counting. Back in the first terminal, plain ps still shows only bash and ps, because it lists this terminal's processes. ps aux lists every process on the computer, from every user (read the letters as all users, user-friendly columns, and processes with no terminal too). That's hundreds of lines, so pipe it into grep (Finding Text: grep) to keep the ones that mention the runaway:
ps aux | grep runaway
sam 1826 99.8 0.0 4952 3648 pts/0 R+ 07:32 0:26 bash ./runaway.sh
sam 2048 0.0 0.0 4132 2388 pts/4 S+ 07:32 0:00 grep --color=auto runaway
The columns that matter most, from the left:
- USER: who started it, here sam.
- PID: its number, 1826.
- %CPU: how much of one processor core it's using. 99.8 is a whole core, busy every moment.
- %MEM: its share of the computer's memory, here almost none.
- TTY:
pts/0, the second terminal. - COMMAND: what's running. A script shows up as
bashfollowed by the script's name, because bash is the program running it.
The second line is grep itself: it was running while ps looked, and its own command has runaway in it. Skip that line.
Who's slowing things down? Sort the list
When you don't know the culprit's name yet, let ps sort. --sort=-%cpu puts the highest CPU first (the - means highest first), and head -n 2 keeps the header and the top line:
ps aux --sort=-%cpu | head -n 2
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
sam 1826 99.8 0.0 4952 3648 pts/0 R+ 07:32 0:27 bash ./runaway.sh
There's the culprit. When a computer has run out of memory instead, sort by -%mem. The columns this lesson skips (memory in kilobytes, the state, the start time) are explained in man ps. On a Mac, ps aux works too, but its ps has no --sort: ps aux -r sorts by CPU, and ps aux -m by memory.
A live view: top and htop
ps takes a snapshot. top keeps the list on the screen and updates it every few seconds, busiest first, until you press q. Plain top fills the screen with every process; -p and a PID watch only that one:
top -p 1826
top - 07:33:03 up 3:56, 1 user, load average: 0.50, 0.25, 0.26
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
%Cpu(s): 4.3 us, 0.2 sy, 0.0 ni, 95.3 id, 0.0 wa, 0.0 hi, 0.2 si, 0.0 st
MiB Mem : 64194.9 total, 60608.1 free, 1999.1 used, 2173.5 buff/cache
MiB Swap: 16384.0 total, 16384.0 free, 0.0 used. 62195.8 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1826 sam 20 0 4952 3648 3360 R 99.7 0.0 0:34.56 bash
The five lines at the top are about the whole computer: how long it has been on, its processes, its processors and its memory. This computer has many processor cores, so as a whole it's only about 4% busy (4.3 us, work for user programs), while one core is flat out: that's the runaway's 99.7. Below them is one line per process, with columns much like ps aux's. While top runs, M sorts by memory and P by CPU again. A Mac's top looks different; top -o cpu puts the busiest first.
htop is a friendlier top: a bar for each processor core and for memory, colors, and a list you can scroll with the arrow keys. Installing it changes your computer, so sudo asks for your password (Installing Tools: Homebrew and apt):
sudo apt install htop # Ubuntu, and Ubuntu in WSL
brew install htop # a Mac, with Homebrew
Run htop, press F4 to filter, and type runaway to keep only its line. q quits.
When you've seen enough, go back to the second terminal and press Ctrl+C to stop the runaway.
Check yourself
2 questions to try on the lesson page.
So what
When a computer slows down, ps aux --sort=-%cpu or top names the process doing it in seconds, on your laptop or on a server with no screen at all, and its PID is what you need to stop it.