top

Which processes are using the machine right now

Updated 2026-09-30

top redraws a table of processes every few seconds, busiest first, under five summary lines about the machine as a whole. Run with no arguments it takes over the terminal until you press q.

Most of what people do in it is a single key:

  • P sorts by CPU, and M by memory.
  • 1 splits the CPU line into one line per core.
  • H shows threads instead of processes.
  • c shows each process's full command line.
  • u asks for a user to filter on.
  • k asks for a process ID and a signal, and sends it.
  • r renices a process.
  • W saves the current layout to ~/.config/procps/toprc, so the next top starts the same way.

A keypress is not something that can be simulated here, so the examples on this page use the flag that does the same job.

Every example runs in batch mode, -b, which prints plain text and exits after the number of updates -n asks for. It is also how top is used from a script or a cron job, where there is no terminal to draw on. ps prints the same process information once, and is easier to parse. top is better for watching what happens over the next few seconds.

The summary lines describe the machine: its uptime and load, how its CPUs are spending their time, and the memory and swap figures free also prints. Inside a container those belong to the host, so they differ between any two runs. The task count and the process list below it belong to whatever ran the command, and the examples that read the list start three processes of their own, so their names, owners and states are the same every time.

Sample files used on this page

Every example below was run against these files. Recreate them to follow along.

the processes the examples read Started by the setup script and left running. spinner is a copy of gawk running an empty loop, so it is always ready to run and all its time is user time. sleeper is a copy of sleep, run as user, and is the only process that account owns. memhog is a copy of python3 that has written 200 MiB and started two idle threads. Copies, because top shows the name of the file a process was started from. The columns are the owner, the state, the number of threads and the name.

root     R    1 spinner
user     S    1 sleeper
root     S    3 memhog
21 outputs, collapsed by default

The summary lines

Five lines about the machine as a whole, above the process list. Apart from the task count, every figure in them belongs to the machine and moves from one second to the next, so the examples here show the lines as they were captured, and check what can be said about them on any machine.

Take one snapshot of the whole machine

top -b -n1 | head -5

-b prints plain text rather than drawing on the terminal, and -n1 stops after one update. The first line is the clock, the uptime, the logged-in users and the load average over one, five and fifteen minutes. The second counts processes by state. The third splits CPU time into user (us), system (sy), niced (ni), idle (id), waiting for disk (wa), and three kinds a virtual machine or interrupts take. The last two are the figures free prints.

Show output
top - 15:22:00 up 4 days, 22:51,  0 users,  load average: 1.21, 0.71, 0.76
Tasks:   7 total,   2 running,   5 sleeping,   0 stopped,   0 zombie
%Cpu(s): 12.6 us,  1.1 sy,  0.0 ni, 86.2 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   3916.4 total,    590.2 free,   2377.5 used,   1144.1 buff/cache
MiB Swap:   1024.0 total,    404.2 free,    619.8 used.   1538.9 avail Mem

Confirm the CPU states add up to 100%

top -b -n2 -d 0.5 | awk '/^%Cpu\(s\)/ {line = $0} END {gsub(/,/, " ", line); n = split(line, f, " "); for (i = 1; i <= n; i++) if (f[i] ~ /^[0-9.]+$/) s += f[i]; print (s > 99.5 && s < 100.5) ? "the CPU states add up to 100%" : "the CPU states do not add up to 100%"}'

Why this example is here: The command in “Take one snapshot of the whole machine” prints figures that belong to the machine it runs on, so its output is different everywhere and cannot be checked the way the rest of the examples on this site are. This command is here to check what the page says about that output instead. It works the claim out and prints the answer, and that answer is re-run on every change. You are unlikely to need it yourself.

Sums every figure on the CPU line of the second update, which covers the half-second period set by -d 0.5. The eight states are shares of one total, so they make 100 once rounding is allowed for. The commas are turned into spaces first, because a state at 100.0 is printed with no space before it.

Show output
the CPU states add up to 100%

Confirm top's memory total is the kernel's

[ "$(top -b -n1 | awk '/^MiB Mem/ {print $4}')" = "$(awk '/^MemTotal:/ {printf "%.1f", $2 / 1024}' /proc/meminfo)" ] && echo "top's total is MemTotal in MiB"

Why this example is here: The command in “Take one snapshot of the whole machine” prints figures that belong to the machine it runs on, so its output is different everywhere and cannot be checked the way the rest of the examples on this site are. This command is here to check what the page says about that output instead. It works the claim out and prints the answer, and that answer is re-run on every change. You are unlikely to need it yourself.

Converts MemTotal from /proc/meminfo to mebibytes with one decimal place and compares it with the total top printed. top and free both read their memory figures from /proc/meminfo, so their totals match. Their other figures can differ slightly, because each reads the file at a different moment and memory use changes in between.

Show output
top's total is MemTotal in MiB

Check the task count covers every process listed

top -b -n1 | awk '/^Tasks:/ {t = $2} /^ *PID/ {listed = 1; next} listed && NF {n++} END {print (t == n) ? "the task count is the number of rows listed" : "the task count is not the number of rows listed"}'

Counts the rows under the column headers and compares them with the Tasks total. Unlike the rest of the summary, the task count belongs to whatever ran top: inside a container it is the container's processes, the same ones the list shows.

Show output
the task count is the number of rows listed

Show the memory lines in gibibytes

top -b -n1 -E g | sed -n 4,5p

-E sets the unit for the two memory lines: k, m, g, t, p or e. The default is mebibytes, which puts a large machine's total in the tens of thousands. Pressing E in the running display steps through the same units.

Show output
GiB Mem :      3.8 total,      0.6 free,      2.3 used,      1.1 buff/cache
GiB Swap:      1.0 total,      0.4 free,      0.6 used.      1.5 avail Mem

The process list

One row per process, busiest first. -p picks processes by ID and -u by owner, which is how the examples below keep to the three processes the setup script started, rather than listing whatever else was running.

Name the columns

top -b -n1 | sed -n 7p

PR and NI are the scheduling priority and the nice value. VIRT is the address space the process has mapped, RES how much of it is in memory, and SHR how much of RES is shared with other processes, all in kibibytes. S is the state, %CPU its share of one CPU since the last update, %MEM its RES as a percentage of all the memory the machine has, so 5.3 means the process holds 5.3% of it, and TIME+ the CPU time it has used since it started.

Show output
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND

Watch one process

top -b -n1 -p "$(pgrep -x memhog)" | tail -n +7

-p takes a process ID, or several separated by commas, and lists only those. pgrep -x finds the ID from an exact name. tail -n +7 drops the five summary lines and the blank line after them.

Show output

Your output will differ: the PID, the memory figures, %MEM and TIME+ differ from run to run, and %MEM also depends on how much memory the machine has

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
     26 root      20   0  366348 213492   5516 S   0.0   5.3   0:00.16 memhog

Measure a process's CPU over half a second

top -b -n2 -d 0.5 -p "$(pgrep -x spinner)" | tail -1

-n2 takes two updates and -d 0.5 puts half a second between them, so the row tail -1 keeps belongs to the second update, and its %CPU covers that half-second. The first update has only a very short interval to measure over. %CPU is a share of one CPU, so a process busy on four cores shows 400.

Show output

Your output will differ: the PID, %CPU, the memory figures and TIME+ differ from run to run

     20 root      20   0    5944   2880   2572 R 100.0   0.1   0:01.14 spinner

Tell running from sleeping

top -b -n1 -p "$(pgrep -x spinner),$(pgrep -x sleeper)" | awk 'NR > 7 {print $12, $8}'

The name and the S column. R is running or ready to run, S is asleep waiting for something, and D is waiting for disk and cannot be interrupted, which is the state that pushes the load average up without using any CPU. A process that stays R is the one using the CPU.

Show output
spinner R
sleeper S

Only show one user's processes

top -b -n1 -u user | tail -n +7

-u matches the effective user, the one a process runs with. -U matches the real, effective, saved or filesystem user, so it also lists a setuid program that someone else started. The name or the numeric uid both work.

Show output

Your output will differ: the PID, the memory figures, %MEM and TIME+ differ from run to run

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
     23 user      20   0    2312   1240   1152 S   0.0   0.0   0:00.00 sleeper

Show each process's full command line

top -b -n1 -c -w 100 -u user | tail -n +7

-c shows the arguments as well as the name, which is what tells apart ten processes all called python3. Batch mode lays out 80 columns, which cuts a long command line off, so -w sets a wider page.

Show output

Your output will differ: the PID, the memory figures, %MEM and TIME+ differ from run to run

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
     23 user      20   0    2312   1240   1152 S   0.0   0.0   0:00.00 sleeper infinity

Show a process's threads

top -b -n1 -H -p "$(pgrep -x memhog)" | tail -n +7

-H lists threads instead of processes. Each thread has an ID of its own, from the same range as process IDs, and the first one's is the process ID. A program pinned at 100% can be one busy thread among many idle ones, and this is how to see which.

Show output

Your output will differ: the IDs, the memory figures, %MEM and TIME+ differ from run to run

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
     26 root      20   0  366348 213492   5516 S   0.0   5.3   0:00.16 memhog
     38 root      20   0  366348 213492   5516 S   0.0   5.3   0:00.00 memhog
     39 root      20   0  366348 213492   5516 S   0.0   5.3   0:00.00 memhog

Hide processes that are doing nothing

top -b -n1 -i -u user | tail -n +7

-i leaves out processes that have used no CPU since the last update. user owns only a process that is asleep, so what is left is the header. On a busy machine this cuts a list of hundreds down to the few doing the work.

Show output
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND

Sorting

The list is sorted by %CPU unless told otherwise. -o takes any field name top -O lists, and a - in front of the name reverses it.

Sort by memory

top -b -n1 -o %MEM | sed -n 8p

The first row under the header, with the list sorted by memory. Pressing M in the running display does the same.

Show output

Your output will differ: the PID, the memory figures, %MEM and TIME+ differ from run to run

     26 root      20   0  366348 213492   5516 S   0.0   5.3   0:00.16 memhog

Sort by the CPU time used so far

top -b -n1 -o TIME+ | sed -n 8p

%CPU is what a process is doing now, and TIME+ is everything it has done since it started. A process that is quiet at the moment but has used hours of CPU sorts to the top here, and never would by %CPU.

Show output

Your output will differ: the PID, %CPU, the memory figures and TIME+ differ from run to run

     20 root      20   0    5944   2896   2588 R 100.0   0.1   0:02.87 spinner

List the fields top can show and sort by

top -O | head -5

Every field name, one per line. More than seventy of them, most of which are not shown until they are turned on with f in the running display.

Show output
PID
PPID
UID
USER
RUID

Reading a process's memory

Figures about the processes this page's setup script started, rather than about the machine they run on, so they can be checked here as they are.

Show a process's memory in mebibytes

top -b -n1 -e m -p "$(pgrep -x memhog)" | tail -n +7

-e sets the unit for the memory columns in the list, as -E does for the summary. memhog wrote 200 MiB, and RES is a little over that: the Python interpreter holding it takes some memory of its own.

Show output

Your output will differ: the PID, the memory figures, %MEM and TIME+ differ from run to run

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
     26 root      20   0  357.8m 208.5m   5.4m S   0.0   5.3   0:00.16 memhog

Check that RES is the memory a process has used

top -b -n1 -p "$(pgrep -x memhog)" | awk 'NR == 8 {print ($6 >= 204800) ? "memhog holds at least 200 MiB" : "memhog holds less than 200 MiB"}'

RES counts the pages that are in memory, which for memhog includes the 200 MiB it wrote. 204800 is 200 MiB in kibibytes, the unit the column uses.

Show output
memhog holds at least 200 MiB

Check that VIRT is at least RES

top -b -n1 -p "$(pgrep -x memhog)" | awk 'NR == 8 {print ($5 >= $6) ? "VIRT is at least RES" : "VIRT is less than RES"}'

VIRT counts everything the process has mapped, whether it has touched it or not, so it is never smaller than RES. A large VIRT on its own means little: a program can map far more than it will ever use.

Show output
VIRT is at least RES

Check that threads share their process's memory

top -b -n1 -H -p "$(pgrep -x memhog)" | awk 'NR > 7 {print $6}' | sort -u | wc -l

Every thread of memhog shows the same RES, so there is one distinct value. Threads share the process's memory, and adding up the thread rows of top -H counts the same memory once per thread.

Show output
1

Scripts and logs

Take several snapshots in a row

top -b -n 3 -d 0.2 | grep -c "^top -"

Counts the first line of each update. -n sets how many updates, and -d the seconds between them, fractions allowed. Left to itself, batch mode runs until it is killed.

Show output
3

Save a snapshot to read later

top -b -n1 > snapshot.txt

The whole display as text, which is worth doing from cron every few minutes on a machine that slows down at night. By the time anyone looks, whatever was busy has usually finished.