Skip to content

Live Monitoring Processes — top, htop


Every process-inspection tool so far — ps, pgrep, lsof — gives you a snapshot: accurate at the instant you ran it, frozen from then on. That’s fine for most troubleshooting, but sometimes the question isn’t “what’s the state right now,” it’s “what’s happening as I watch.” A process spiking CPU intermittently, memory climbing steadily over several minutes, a system that feels slow but no single ps snapshot explains why — these need a live view. That’s top.

Starting top

top

The screen takes over your terminal and starts refreshing automatically — by default, every few seconds — showing you a live, continuously updating picture of the system. Nothing else runs in that terminal while top has it; press q to quit and get your prompt back.

Reading The Header

Before the process list even starts, top shows a summary block worth understanding line by line:

top - 14:32:07 up 3 days,  4:12,  2 users,  load average: 0.52, 0.68, 0.71
Tasks: 187 total,   1 running, 186 sleeping,   0 stopped,   0 zombie
%Cpu(s):  3.2 us,  1.1 sy,  0.0 ni, 95.4 id,  0.2 wa,  0.0 hi,  0.1 si,  0.0 st
MiB Mem :   7943.2 total,   2104.5 free,   3211.8 used,   2626.9 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   4302.1 avail Mem

The load average is the number people quote most often, and it’s the one most often misread. Three numbers, representing the average system load over the last 1, 5, and 15 minutes respectively. “Load” here roughly means the number of processes wanting CPU time — either running or waiting their turn. On a single-CPU system, a load average of 1.0 means the CPU is fully occupied, on average, over that window; anything meaningfully above 1.0 means processes are queuing up waiting for their turn. On a multi-core system, that threshold scales with the number of cores — a load average of 4.0 is entirely healthy on an 8-core machine, but a real problem on a 2-core one. There’s no universal “bad number” without knowing how many cores you’re comparing it against.

The Tasks line breaks down process states, using exactly the vocabulary from the What Is A Process chapter — running, sleeping, stopped, zombie. A nonzero zombie count here is worth remembering the earlier caution about: it’s the parent’s job to clean those up, not something top itself can fix.

The %Cpu(s) line splits CPU time into categories — us (user processes), sy (kernel/system work), id (idle, doing nothing), wa (waiting on I/O), among others. A high wa value specifically is worth flagging: it means the CPU is sitting idle not because there’s no work to do, but because processes are stuck waiting on disk or network — a sign to go looking at storage or network performance, not CPU-bound code.

The memory lines show total, free, used, and — importantly — buff/cache, memory the kernel is using for disk caching, which it will readily give back the moment an application actually needs it. A system showing very little “free” memory isn’t necessarily in trouble; Linux deliberately uses spare memory for caching rather than leaving it idle, and that memory is reclaimed on demand.

The Process List

Below the header, top shows a live, continuously refreshing process list, similar in shape to ps aux but updating in place:

  PID USER      PR  NI    VIRT    RES  %CPU  %MEM  TIME+  COMMAND
 2044 you       20   0  412108  45120   4.3   0.6  0:12.44 firefox

Most of these columns match what you already know from the ps chapter — %CPU, %MEM, VIRT (equivalent to ps’s VSZ), RES (equivalent to RSS). The genuinely new pieces are PR (scheduling priority) and NI (“niceness,” which we’ll leave as a pointer forward rather than a full detour here — it controls how favorably the kernel schedules a process, and it’s a small enough topic that it doesn’t need its own chapter, but it’s worth knowing the column exists).

By default, top sorts by %CPU, highest first — the live equivalent of ps aux --sort=-%cpu from the last ps chapter, except this one keeps re-sorting continuously as usage changes in front of you.

Interacting With top While It’s Running

top isn’t just a passive display — a handful of keystrokes control it while it’s open:

KeyAction
qQuit
MSort by memory usage instead of CPU
PSort by CPU usage (the default)
kKill a process by PID (prompts you to enter one)
1Toggle showing per-core CPU breakdown instead of one aggregate line

That k shortcut is worth knowing exists, but hold off on reaching for it yet — killing a process safely involves more judgment than a single keystroke suggests, and that’s covered properly with the caution it deserves in the Killing Processes chapter shortly. For now, know it’s there.

To make the Linux top command display memory sizes (like VIRT, RES, and SHR) in a human-readable format (e.g., megabytes or gigabytes instead of raw kilobytes), press the e key while the program is actively running.

Keyboard Shortcuts: You can dynamically toggle the data scale using these keys:

  • e: Cycles the process list memory units through KiB, MiB, GiB, TiB, PiB, and EiB.
  • E (Shift + e): Cycles the system summary memory units (the top text area) through the same units.
  • W (Shift + w): Saves your unit choice permanently to your configuration file (~/.toprc) so it loads automatically next time.

Tip

Instead of remembering shortcuts, make a habit of using top or htop and use help (press h). Practice makes you perfect.

htop: The Friendlier Alternative

top is universal — it’s installed by default on essentially every Linux system you’ll ever touch, which is exactly why it’s worth knowing well even though it looks dated. htop is a more modern, more readable alternative, but it isn’t always installed by default and may need to be added yourself:

sudo apt install htop
htop

Reading htop’s Header

The numbered bars (0 through 11) are per-core CPU usage — one bar per logical CPU core, each filled proportionally to that specific core’s current load, with its percentage printed alongside. This is the detail top’s default aggregate %Cpu(s) line hides entirely — a single busy core on an otherwise idle multi-core machine shows up clearly here as one full bar among many empty ones, exactly the kind of thing you’d otherwise mistake for “the system is fine” when checking only an aggregate.

Mem[...] is a visual bar for physical memory in use, with the same used/total figure top’s memory line gave you as text — here shown as a proportionally filled bar instead, 1.38G/7.44G in the screenshot.

Swp[...] is the equivalent bar for swap usage — space reserved on disk that the kernel uses as overflow when physical memory runs low. 0K/2.00G here means swap exists but nothing is currently using it, generally a healthy sign; a swap bar filling up over time, especially alongside a mostly-full Mem bar, is a classic early symptom of a system running short on memory.

Tasks: 49, 158 thr, 0 kthr; 1 running breaks down differently from top’s Tasks line. 49 is the total process count, matching the vocabulary from the What Is A Process chapter. 158 thr is the total number of threads across all those processes — a single process can contain many threads, each an independent execution path sharing that process’s memory, which is why this number is so much larger than the process count and isn’t the same thing as a separate process. 0 kthr counts kernel threads specifically — threads belonging to the kernel itself rather than to any user-space process. 1 running matches the R state from the What Is A Process chapter — just how many of those 49 processes are actively executing on a core at this exact instant, rather than sleeping.

Load average: 0.14 0.17 0.08 is the exact same 1/5/15-minute figure from top’s header, interpreted the same way — on this 12-core machine (given 12 numbered CPU bars, 0 through 11), a load average under 1.0 across all three windows means the system is barely loaded at all, nowhere near the per-core saturation point discussed when this figure was first introduced.

Uptime: 00:21:28 is simply how long the system has been running since its last boot — not present on top’s default header at all, one of the small conveniences htop adds without you having to run a separate command for it.

The core ideas are identical — live process view, sortable, interactive — but htop adds real usability improvements: color-coded, per-core CPU bars right in the header, mouse support, scrolling through a long process list instead of it just running off the bottom of the screen, and killing or renicing a process through an on-screen menu rather than memorizing a keystroke.

I also found this article explaning htop in more detailed view. However, this should be more than enough to start using htop. The more you use, the more you know the tool.

    flowchart LR
    A["Need a one-time snapshot,<br/>scriptable, precise"] --> B["ps"]
    C["Need to watch behavior<br/>unfold over time"] --> D["top / htop"]
    D --> E["top: always available,<br/>no install needed"]
    D --> F["htop: friendlier,<br/>may need installing"]
  

Which One Should You Actually Use

Default to htop when it’s available and you’re troubleshooting interactively — it’s simply easier to read at a glance. But treat top as the one you actually need to be fluent in, since it’s the one guaranteed to exist on any system you’re dropped into, including minimal server installs where nothing beyond the base system has been added. Being comfortable reading raw top output, load average and all, is the more transferable skill of the two.

What’s Next

You now have a live view of process behavior to go alongside the static snapshots from ps. Everything up to this point has been about inspecting processes. The next chapter shifts to actually controlling them — starting with the concept underlying that entirely, before touching kill itself: what a signal actually is.

Last updated on