The top command in Linux is the primary built-in tool for real-time system monitoring, enabling administrators to inspect CPU utilization, memory consumption, per-process resource usage, and load averages from a single interactive view. Whether you are troubleshooting CPU-bound services, tracking memory leaks, or capturing snapshots for historical analysis, mastering top helps you diagnose performance bottlenecks quickly. This guide covers practical examples, interactive controls, batch-mode usage for scripting, interpretation of key fields (VIRT, RES, SHR, %CPU, %MEM), and tips for using top effectively across Debian, Ubuntu, RHEL, CentOS, and Arch systems.
Overview and When to Use top
top provides a live, updating display of the system’s most important metrics: system uptime and load averages, task counts and states, CPU state percentages, memory and swap usage, and a sortable process table. Use top for quick ad-hoc checks when investigating: unexpected load spikes, high I/O wait, runaway processes, memory pressure, or to confirm whether a service restart resolved a resource issue. Unlike ps, top is interactive and continuously refreshes its output, making it ideal for live troubleshooting. Below are practical commands and realistic sample outputs you can use immediately on production or lab systems.
Start top (interactive snapshot)
top top - 11:24:37 up 12 days, 3:41, 2 users, load average: 0.28, 0.30, 0.25 Tasks: 212 total, 1 running, 210 sleeping, 0 stopped, 1 zombie %Cpu(s): 4.7 us, 2.0 sy, 0.0 ni, 92.6 id, 0.6 wa, 0.0 hi, 0.1 si, 0.0 st MiB Mem : 15886.7 total, 8231.4 free, 4912.5 used, 2742.8 buff/cache MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 10374.2 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1234 www-data 20 0 123456 45678 9012 S 4.3 0.3 0:42.31 nginx 987 mysql 20 0 987654 321098 12345 S 1.7 2.0 3:12.04 mysqld 5678 root 20 0 65432 5678 3456 S 0.0 0.0 0:00.12 sshd
Running top without flags opens the interactive monitor. The header shows uptime and load averages, task and CPU summaries, and memory usage. The task table lists PID, owner, priority, VIRT/RES/SHR, state, CPU/memory percentages, total CPU time, and the command. Use the interactive keys (P/M/N/T, k, r, 1, c, u) to sort, kill, renice, and filter.
Change refresh interval
top -d 2 top - 11:26:10 up 12 days, 3:43, 2 users, load average: 0.31, 0.30, 0.25 Tasks: 212 total, 1 running, 210 sleeping, 0 stopped, 1 zombie %Cpu(s): 5.1 us, 1.9 sy, 0.0 ni, 92.5 id, 0.4 wa, 0.0 hi, 0.1 si, 0.0 st MiB Mem : 15886.7 total, 8098.1 free, 5045.8 used, 2742.8 buff/cache MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 10374.2 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2345 nginx 20 0 234560 45670 8900 S 6.5 0.3 1:10.05 nginx 1987 postgres 20 0 1123456 512000 23000 S 2.0 3.2 4:01.22 postgres
The -d flag sets the delay between updates in seconds. In this example -d 2 refreshes every 2 seconds; it’s useful when you need quicker feedback than the default interval.
Batch mode: capture a snapshot for scripts or logs
top -b -n 1 top - 11:28:01 up 12 days, 3:45, 2 users, load average: 0.35, 0.30, 0.26 Tasks: 212 total, 1 running, 210 sleeping, 0 stopped, 1 zombie %Cpu(s): 6.0 us, 2.3 sy, 0.0 ni, 91.1 id, 0.6 wa, 0.0 hi, 0.0 si, 0.0 st MiB Mem : 15886.7 total, 7920.4 free, 4963.5 used, 3002.8 buff/cache MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 10374.2 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3456 java 20 0 3456789 512345 56789 S 12.4 3.2 120:45.12 java 987 mysql 20 0 987654 321098 12345 S 2.1 2.0 3:12.04 mysqld
Use -b (batch mode) together with -n to specify iterations. -b -n 1 prints a single snapshot suitable for redirecting to a file or piping into parsing tools like awk, sed, or grep for automated reporting.
Filter by user or PID
top -u root top - 11:30:02 up 12 days, 3:47, 2 users, load average: 0.34, 0.30, 0.25 Tasks: 18 total, 0 running, 18 sleeping, 0 stopped, 0 zombie %Cpu(s): 4.0 us, 1.8 sy, 0.0 ni, 94.0 id, 0.2 wa, 0.0 hi, 0.0 si, 0.0 st MiB Mem : 15886.7 total, 8122.1 free, 4726.5 used, 3038.1 buff/cache MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 10374.2 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 5678 root 20 0 65432 5678 3456 S 0.0 0.0 0:00.12 sshd 2349 root 20 0 23456 10240 5600 S 0.1 0.1 0:02.35 systemd
Use -u to restrict the display to processes owned by a particular user. This is helpful when auditing a specific service account or debugging permission-limited tasks.
Monitor specific PIDs or multiple processes
top -p 1234,5678 top - 11:32:10 up 12 days, 3:49, 2 users, load average: 0.30, 0.29, 0.24 Tasks: 2 total, 0 running, 2 sleeping, 0 stopped, 0 zombie %Cpu(s): 3.2 us, 1.1 sy, 0.0 ni, 95.3 id, 0.4 wa, 0.0 hi, 0.0 si, 0.0 st MiB Mem : 15886.7 total, 8231.4 free, 4912.5 used, 2742.8 buff/cache MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 10374.2 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1234 www-data 20 0 123456 45678 9012 S 4.0 0.3 0:42.31 nginx 5678 root 20 0 65432 5678 3456 S 0.0 0.0 0:00.12 sshd
The -p option accepts comma-separated PIDs so you can focus on a small set of processes (for example, multiple workers belonging to the same service) and ignore system noise.
Show threads instead of processes
top -H top - 11:34:20 up 12 days, 3:51, 2 users, load average: 0.33, 0.31, 0.27 Tasks: 312 total, 5 running, 307 sleeping, 0 stopped, 0 zombie %Cpu(s): 12.8 us, 3.5 sy, 0.0 ni, 83.2 id, 0.4 wa, 0.0 hi, 0.0 si, 0.1 st MiB Mem : 15886.7 total, 7122.4 free, 5921.5 used, 2842.8 buff/cache MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 10374.2 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 4123 appuser 20 0 512000 120000 34000 R 35.0 0.8 150:12.33 java 4124 appuser 20 0 512000 120012 34000 R 15.2 0.8 50:22.10 java.worker-1
The -H flag expands threads into individual lines so that each thread within a multi-threaded process appears separately. This is essential when profiling thread contention or identifying which thread consumes CPU.
Install top if missing
sudo apt-get install -y procps Reading package lists... Done Building dependency tree Reading state information... Done The following NEW packages will be installed: procps 0 upgraded, 1 newly installed, 0 to remove and 12 not upgraded. Need to get 104 kB of archives. After this operation, 416 kB of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu focal/main amd64 procps amd64 2:3.3.16-1ubuntu2 [104 kB] Fetched 104 kB in 0s (524 kB/s) Selecting previously unselected package procps. (Reading database ... 254321 files and directories currently installed.) Preparing to unpack .../procps_2%3a3.3.16-1ubuntu2_amd64.deb ... Unpacking procps (2:3.3.16-1ubuntu2) ... Setting up procps (2:3.3.16-1ubuntu2) ... Processing triggers for man-db (2.9.1-1) ...
If top is not available, install the package that provides it. On Debian/Ubuntu this is procps (or procps-ng on some distributions). On RHEL/CentOS use yum install procps-ng or dnf install procps-ng depending on your OS version.
Interpreting key fields and CPU states
Understanding the top header is crucial. The load average values represent the average number of runnable or uninterruptible tasks over 1, 5, and 15 minutes — values above the number of CPU cores indicate CPU contention. The %Cpu(s) line breaks CPU time into states: us (user), sy (system), ni (nice), id (idle), wa (I/O wait), hi (hardware interrupts), si (software interrupts), and st (steal time for VMs). High wa suggests disk or network I/O bottlenecks; high us or sy means CPU pressure from userland or kernel operations respectively.
The process columns VIRT, RES, and SHR describe memory usage: VIRT is the total virtual address space, RES is resident memory in RAM, and SHR is the portion of RES that is shared (libraries, shared memory). The %CPU is measured since last refresh and can spike briefly, while TIME+ shows cumulative CPU time consumed by the process since start.
Sorting, filtering, and interactive controls
While top is running, use these keys for rapid control: P to sort by CPU, M by memory, N by PID, T by runtime, 1 to toggle per-CPU display, c to toggle full command line, k to send a signal (kill), r to renice, and u to filter by user. Use the field management screen (press f) to add or remove columns and q to quit. Learn to combine sorting and filtering so you can surface the most relevant processes quickly.
Using top in scripts and automated monitoring
Batch mode (-b) is the primary way to integrate top into scripts. Capture periodic snapshots with -n and redirect to a log file for later analysis. When parsing top output in automation, prefer tools like ps, pidstat, or sar for structured data; however top is handy for quick dumps. Example: cron job that runs top -b -n 1 every minute and appends to a rotating log can provide a simple resource timeline during an incident.
Troubleshooting tips and best practices
1) If you see sustained high %wa, run iostat or iotop to confirm disk I/O issues. 2) For memory pressure, check RES vs. available memory and look for processes with growing RES values indicating leaks. 3) If zombie processes accumulate, identify the parent process (PPID) and investigate why it’s not reaping children. 4) Use renice carefully to lower priority of noisy processes; use systemd slice and cgroups for robust resource control in production. 5) For containers and VMs, consider that top may show host metrics differently — use container-aware tools when necessary.
Conclusion
The top command in Linux is an indispensable, lightweight tool for real-time process and system monitoring. By learning its interactive keys, understanding header metrics (CPU states, memory statistics, load averages), and using batch mode for logging, you can rapidly diagnose performance problems and collect evidence during incidents. Combine top with ps, pgrep, iotop, and systemd tools for a comprehensive troubleshooting workflow, and remember that htop provides a more user-friendly alternative if you prefer a richer interactive interface.