opscape

Processes and jobs

top

Show a live, sorted view of processes and system load; batch mode prints snapshots for logs and scripts.

top [-b] [-n ITERATIONS] [-d SECONDS] [-p PID,...] [-u USER] [-o FIELD]

10 of 10 examples run in Debian 13.7 on 2026-10-31 · procps 2:4.0.4-9 · manual: top(1)

top redraws a table of processes every few seconds, sorted by CPU use by default, under a summary header: uptime and load average, task counts by state, CPU time split (us user, sy kernel, wa waiting on I/O, st stolen by the hypervisor) and memory and swap totals. It is the first thing to run when a machine feels slow: the top line tells you whether it is CPU, I/O wait or memory, and the process list tells you who.

Interactively, a few keys do most of the work: P sorts by CPU, M by memory, c toggles full command lines, 1 splits the CPU line per core, k kills a process by PID, u filters by user, H shows threads, q quits. Those keys need a terminal; none of them can be shown here.

With -b (batch mode) top writes plain text to standard output instead of drawing on the screen, and -n limits how many updates it prints. That is the form for scripts, logs and remote one-off checks (ssh host 'top -b -n 1 | head -20'), and the one used below. The examples run in a container that shares the build machine's kernel, so the header's uptime, load and memory figures describe that machine; the examples cut the header off and show only the process list, which is the part that belongs to the sandbox. Header lines are the first five, then a blank line, so the column header is line 7.

Examples

Print one snapshot of the process list

top -b -n 1 | tail -n +7
explain
output
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
      1 root      20   0  253812  18280   5988 S   0.0   0.0   0:23.48 python3
      8 root      20   0   11768   3360   2136 S   0.0   0.0   0:00.10 sshd
   3465 dev       20   0    4488   2356   2096 S   0.0   0.0   0:00.00 bash
   3466 dev       20   0    7800   4132   2100 R   0.0   0.0   0:00.00 top
   3467 dev       20   0    3048   1420   1312 S   0.0   0.0   0:00.00 tail

-b writes plain text and -n 1 stops after one update. tail -n +7 skips the five summary lines and the blank line. PR and NI are the scheduling priority and nice value, VIRT, RES and SHR memory in KiB, S the state and TIME+ CPU time as minutes:seconds.hundredths.

Find the process that is burning CPU

python3 -c 'while True: pass' &
sleep 1
top -b -n 1 -o %CPU | sed -n '7,10p'
output
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   3469 dev       20   0   14860   6776   4020 R 100.0   0.0   0:01.19 python3
      1 root      20   0  253812  18280   5988 S  10.0   0.0   0:23.54 python3
      8 root      20   0   11768   3360   2136 S   0.0   0.0   0:00.10 sshd

A busy loop in the background, then one snapshot sorted by %CPU (also the default). %CPU is measured over the last interval and is per core, so a multi-threaded process can show more than 100 on a multi-core machine.

Watch specific processes over time

python3 -c 'while True: pass' &
top -b -n 3 -d 0.5 -p $! | grep -A1 '^ *PID'
output
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   3474 dev       20   0   14860   6692   3932 R 100.0   0.0   0:00.20 python3
--
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   3474 dev       20   0   14860   6692   3932 R 100.0   0.0   0:00.70 python3
--
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   3474 dev       20   0   14860   6692   3932 R 100.0   0.0   0:01.20 python3

-p limits the display to the listed PIDs (comma-separated), -d 0.5 sets the interval in seconds and -n 3 prints three updates. grep -A1 keeps each column header and the line after it; TIME+ grows by about half a second of CPU per update.

Show only one user's processes, with full command lines

sleep 300 &
top -b -n 1 -c -u dev -w 100 | tail -n +7
output
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   3477 dev       20   0    4488   2400   2144 S   0.0   0.0   0:00.00 /bin/bash -c sleep 300 & to+
   3478 dev       20   0    3012   1428   1320 S   0.0   0.0   0:00.00 sleep 300
   3479 dev       20   0    7804   4184   2144 R   0.0   0.0   0:00.00 top -b -n 1 -c -u dev -w 100
   3480 dev       20   0    3048   1408   1292 S   0.0   0.0   0:00.00 tail -n +7

-u dev filters by effective user, -c shows the command line instead of the program name, and -w 100 widens the output to 100 columns. A + at the end of a column marks a value that did not fit.

Sort by memory use

python3 -c 'import time; x = bytearray(50_000_000); time.sleep(30)' &
sleep 0.5
top -b -n 1 -o RES | sed -n '7,10p'
output
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   3482 dev       20   0   63692  55712   4128 S   0.0   0.0   0:00.03 python3
      1 root      20   0  253812  18280   5988 S   0.0   0.0   0:23.64 python3
   3484 dev       20   0    7800   4172   2136 R   0.0   0.0   0:00.00 top

-o FIELD picks the sort column by its header name: RES (resident memory), %MEM, TIME+, PID. Prefix it with - (-o -RES) to sort ascending. The Python process holding a 50 MB buffer comes first.

Show task memory in larger units

python3 -c 'import time; x = bytearray(50_000_000); time.sleep(30)' &
sleep 0.5
top -b -n 1 -e m -p $! | tail -n +7
output
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   3487 dev       20   0   62.2m  54.4m   4.0m S   0.0   0.0   0:00.03 python3

-e scales the per-process memory columns: k, m, g, t or p. With m the values are MiB with a trailing m. (-E does the same for the summary header.)

Show the threads of a process

python3 -c 'import threading, time
for _ in range(2): threading.Thread(target=time.sleep, args=(30,)).start()' &
sleep 0.3
top -b -n 1 -H -p $! | tail -n +7
output
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   3492 dev       20   0  162360   7572   4344 S   0.0   0.0   0:00.00 python3
   3494 dev       20   0  162360   7572   4344 S   0.0   0.0   0:00.00 python3
   3495 dev       20   0  162360   7572   4344 S   0.0   0.0   0:00.00 python3

-H lists each thread as its own line. The PID column then holds thread IDs; all three lines belong to one Python process (the main thread plus two workers), which is why they share the same memory figures.

Record snapshots to a file for later

python3 -c 'while True: pass' &
top -b -n 3 -d 0.5 -p $! > top.log
grep -c '^top -' top.log
awk '$1 ~ /^[0-9]+$/ {print $9, $11}' top.log
output
3
100.0 0:00.20
100.0 0:00.70
100.0 0:01.20

Each update starts with a top - line, so counting them confirms three snapshots. The awk line pulls %CPU and TIME+ from the process rows. On a server, top -b -d 60 -n 1440 > day.log keeps a day of minute-by-minute history without installing anything.

List the fields top can display

top -O | head -12
explain
output
PID
PPID
UID
USER
RUID
RUSER
SUID
SUSER
GID
GROUP
PGRP
TTY

-O prints every field name and exits; these are the names -o accepts for sorting. Adding or removing columns is done interactively with f and saved with W to the config file.

Forgetting batch mode in a script

top -n 1 | head -3
echo "top exit status: ${PIPESTATUS[0]}"
output
top: failed tty get
top exit status: 1

Without -b, top needs a terminal to draw on. With output going to a pipe and no terminal it fails with failed tty get and exit status 1. Any top in a cron job, script or CI log needs -b.

Common pitfalls

  • Leaving out -b in scripts and cron jobs: top fails without a terminal, or fills a log with screen-control escape codes when one exists. Always top -b -n 1.

  • Reading %CPU above 100 as a bug. It is per core: 400 on an 8-core machine means four cores' worth. Press 1 (or read the header) to see per-core load, and I toggles Irix mode, which divides by the core count.

  • Judging memory pressure by the free figure. Linux uses spare memory as cache; look at avail Mem in the header (or free -h's available column) instead.

  • In a container, the header shows the host's CPU count, load and memory, while the process list shows only the container's processes.

GNU vs BSD and macOS

The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).

  • macOS top is a different program: batch output is top -l 1 (-l is the sample count), sorting is -o cpu or -o mem (lowercase keys), and there is no -b.

  • FreeBSD top uses -b for batch mode too, but its sort keys (-o cpu, -o res) and other options differ from procps.

  • htop and btop are friendlier interactive alternatives on any system, but they are not installed by default; scripts should stick to top -b or ps.

Options worth knowing

A selection, described in our own words. For the full list, see top(1) or top --help.

OptionWhat it does
-b, --batch-modeWrite plain text to standard output instead of drawing on the screen.
-n, --iterations NUMBERExit after NUMBER updates.
-d, --delay SECONDSWait SECONDS (fractions allowed) between updates.
-p, --pid PIDLISTShow only the listed process IDs (comma-separated).
-u, --filter-only-euser USERShow only processes whose effective user is USER.
-U, --filter-any-user USERShow only processes where any user ID (real, effective, saved) matches USER.
-o, --sort-override FIELDSort by FIELD (a column name such as %MEM or RES); a leading - reverses.
-O, --list-fieldsPrint all field names and exit.
-c, --cmdline-toggleToggle between program names and full command lines.
-H, --threads-showShow each thread as its own line.
-i, --idle-toggleToggle display of idle processes.
-S, --accum-time-toggleToggle cumulative time (include dead children's CPU time).
-e, --scale-task-mem SCALEShow process memory in k, m, g, t or p units.
-E, --scale-summary-mem SCALEShow header memory in k, m, g, t, p or e units.
-w, --width[=COLUMNS]In batch mode, set the output width.
-1, --single-cpu-toggleToggle between one combined CPU line and one per CPU.
-s, --secure-modeRun in secure mode, disabling interactive kill and renice.
-V, --versionPrint the version and exit.

Related