To view running processes in Linux, use ps aux for a snapshot of all current processes with CPU and memory usage, top for a real-time updating display, or htop for a more visual interactive monitor. The ps aux command shows every process on the system with its PID (process ID), owner, CPU percentage, memory percentage, and the command that launched it. Use pgrep processname to find a specific process by name, or pidof processname to get its PID directly.
Processes Are Everything Linux Does
Every action Linux performs happens through a process. Your web browser is a process. The terminal you type commands into is a process. The music player in the background is a process. The system daemon that manages your network connection is a process. Even the Linux kernel creates kernel threads that appear as processes. At any given moment on a typical desktop Linux system, hundreds of processes are running simultaneously — each doing its own work, managed by the Linux kernel’s scheduler.
Understanding processes is fundamental to understanding Linux. When your system feels slow, you check which processes are consuming CPU and memory. When an application stops responding, you find its process and send it a signal. When you want to know if a service is running, you look for its process. When you troubleshoot a system that is behaving unexpectedly, you examine what is running and what should not be.
Linux provides a rich set of tools for viewing, monitoring, and managing processes — from the ubiquitous ps command that takes a snapshot of current processes, to top and htop for real-time monitoring, to pgrep and pstree for finding and visualizing process relationships. This article covers all of these tools comprehensively, with clear explanations of what the output means and how to use the information practically.
What Is a Process?
Before the commands, a clear understanding of what a process is makes everything that follows more meaningful.
Processes vs. Programs
A program is a file on disk — an executable that contains instructions. A process is a running instance of a program — the program loaded into memory, being executed by the CPU, with its own resources (memory space, file handles, network connections).
The same program can have multiple simultaneous processes — open three terminal windows and you have three separate bash processes, each with its own state and memory.
Process Attributes
Every process has several key attributes:
PID (Process ID) — a unique number identifying the process. PIDs are assigned sequentially from 1 upward; when a process terminates, its PID can eventually be reused.
PPID (Parent Process ID) — every process (except PID 1) was created by another process. The PPID identifies that parent. When you run a command in the terminal, the terminal (bash) is the parent process of the command you ran.
UID/GID — the user and group the process runs as. This determines what files and resources the process can access.
State — what the process is currently doing: running, sleeping, waiting for I/O, stopped, or zombie.
Priority and niceness — how much CPU time the scheduler gives this process relative to others.
Memory usage — how much RAM the process has allocated.
CPU usage — what percentage of CPU time the process has consumed.
Process States
| State | Code | Meaning |
|---|---|---|
| Running | R | Actively executing on a CPU |
| Sleeping (interruptible) | S | Waiting for an event (I/O, signal, timer) |
| Sleeping (uninterruptible) | D | Waiting for disk I/O — cannot be interrupted |
| Stopped | T | Paused by a signal (e.g., Ctrl+Z) |
| Zombie | Z | Terminated but parent hasn’t collected exit status |
| Idle | I | Kernel thread with nothing to do |
Most processes spend most of their time in state S (sleeping/waiting). A process in state D (uninterruptible sleep) is usually waiting for a disk or network operation to complete — if a process stays in D for a long time, it often indicates a storage or NFS problem. Zombie processes (Z) are harmless remnants — they disappear when their parent process reads their exit status.
PID 1: The Init System
PID 1 is the first process started by the kernel and the ancestor of all other processes. On modern Linux distributions, PID 1 is systemd — the init system that starts all services and manages the system lifecycle:
$ ps -p 1
PID TTY TIME CMD
1 ? 00:00:05 systemd
ps: The Process Snapshot Command
ps (process status) takes a snapshot of currently running processes. Unlike top, it does not update — it shows the state of processes at the moment you run it. This makes ps ideal for capturing process information in scripts or for quick one-time checks.
ps aux: The Universal Process List
The most commonly used ps invocation shows all processes with detailed information:
$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 168752 13288 ? Ss Feb13 0:05 /sbin/init
root 2 0.0 0.0 0 0 ? S Feb13 0:00 [kthreadd]
root 15 0.0 0.0 0 0 ? I< Feb13 0:00 [rcu_tasks_kthread]
...
sarah 1523 0.2 1.2 2845672 201344 ? Sl 09:22 0:45 /usr/bin/firefox
sarah 1598 3.5 0.8 1234568 135280 pts/0 Sl 09:25 1:23 firefox --renderer
sarah 2145 0.0 0.1 23456 8912 pts/1 Ss 09:30 0:00 bash
sarah 2891 0.0 0.0 11456 3456 pts/1 R+ 10:15 0:00 ps aux
Column meanings:
- USER — which user account owns the process
- PID — the process ID
- %CPU — percentage of CPU time consumed since the process started (can exceed 100% on multi-core systems, showing total across all cores)
- %MEM — percentage of physical RAM currently used
- VSZ — Virtual memory SiZe in KB — total virtual address space allocated (includes memory that may be swapped out or not yet used)
- RSS — Resident Set Size in KB — physical RAM actually in use right now (this is the meaningful memory number)
- TTY — the controlling terminal (
?means no terminal, typical for background daemons) - STAT — process state (see the states table above; additional characters like
smean session leader,+means foreground process group) - START — when the process started
- TIME — total CPU time the process has consumed
- COMMAND — the command that launched the process
Understanding %CPU and %MEM
%CPU in ps aux is averaged over the process’s entire lifetime, not the current moment. A process that used lots of CPU when it started but has been idle shows a lower %CPU over time. For current CPU usage, top is more accurate.
%MEM is based on RSS (physical RAM in use). Note that multiple processes often share memory (shared libraries), so the sum of all %MEM values can exceed 100% — each process counts shared memory in its own total even though it is physically present only once.
RSS vs. VSZ: Always look at RSS for actual memory consumption. VSZ includes memory mappings, memory-mapped files, and reserved space that may not actually be using physical RAM. A process with VSZ of 2 GB but RSS of 200 MB is using 200 MB of physical RAM.
ps aux Sorted by Resource Usage
Find the most CPU-intensive processes:
$ ps aux --sort=-%cpu | head -10
Find the most memory-intensive processes:
$ ps aux --sort=-%mem | head -10
ps with Custom Format
ps supports extensive format customization with -o:
$ ps -eo pid,ppid,user,stat,%cpu,%mem,comm --sort=-%cpu | head -15
PID PPID USER STAT %CPU %MEM COMMAND
1523 522 sarah Sl 3.5 1.2 firefox
1598 1523 sarah Sl 2.8 0.8 Web Content
879 1 root Ssl 0.5 0.3 dockerd
2145 522 sarah Ss 0.0 0.1 bash
1 0 root Ss 0.0 0.0 systemd
Common -o format fields: pid, ppid, user, uid, stat, %cpu, %mem, rss, vsz, comm (command name only), args (full command with arguments), start, time, tty, nice, pri.
ps for a Specific User
$ ps -u sarah
PID TTY TIME CMD
1523 ? 00:00:45 firefox
2145 pts/1 00:00:00 bash
2891 pts/1 00:00:00 ps
ps for a Specific Process
$ ps -p 1523
PID TTY TIME CMD
1523 ? 00:00:45 firefox
ps with Process Hierarchy
$ ps axjf | head -30
Shows processes in a forest/tree format showing parent-child relationships.
top: Real-Time Process Monitor
top displays a continuously updating view of system processes and resource usage — the classic Linux real-time monitoring tool.
$ top
Understanding the top Display
top - 10:35:42 up 5 days, 2:18, 2 users, load average: 0.52, 0.48, 0.45
Tasks: 312 total, 1 running, 311 sleeping, 0 stopped, 0 zombie
%Cpu(s): 3.5 us, 1.2 sy, 0.0 ni, 94.8 id, 0.3 wa, 0.0 hi, 0.2 si, 0.0 st
MiB Mem : 31744.0 total, 1258.2 free, 8524.6 used, 21961.2 buff/cache
MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 22734.8 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1523 sarah 20 0 2782836 201344 87632 S 3.5 0.6 0:45.23 firefox
879 root 20 0 1.8g 52436 31248 S 0.5 0.2 2:13.45 dockerd
1598 sarah 20 0 1206832 135280 62412 S 2.8 0.4 1:23.67 Web Content
1 root 20 0 168752 13288 9876 S 0.0 0.0 0:05.12 systemd
The summary section (top five lines):
Line 1 — system time, uptime, users, and load average (same as uptime command).
Line 2 — task counts: total processes, currently running (on CPU), sleeping, stopped (Ctrl+Z), and zombie.
Line 3 — CPU time breakdown:
us— user space (your programs)sy— system/kernel spaceni— processes with modified nicenessid— idle (available CPU)wa— waiting for I/O (highwaindicates a disk bottleneck)hi— hardware interrupt handlingsi— software interrupt handlingst— stolen (in virtual machines, CPU time taken by hypervisor)
Lines 4–5 — memory and swap, same interpretation as free -h.
The process columns in top:
- PR — actual scheduling priority (lower = higher priority)
- NI — nice value (-20 to +19; lower = higher priority; most processes run at 0)
- VIRT — virtual memory (like VSZ in ps)
- RES — resident memory in use (like RSS in ps — the meaningful number)
- SHR — shared memory
- S — state (R, S, D, T, Z)
- %CPU — current CPU usage percentage (updated each refresh cycle)
- %MEM — current memory percentage
- TIME+ — total CPU time in hundredths of seconds
- COMMAND — process name
Essential top Keyboard Shortcuts
| Key | Action |
|---|---|
q |
Quit |
h or ? |
Help |
P |
Sort by CPU usage (default) |
M |
Sort by memory usage |
T |
Sort by CPU time |
N |
Sort by PID |
R |
Reverse sort order |
1 |
Toggle per-CPU display (shows each core separately) |
m |
Toggle memory display format |
t |
Toggle tasks/CPU display |
k |
Kill a process (prompts for PID) |
r |
Renice a process (change priority) |
u |
Show only processes for a specific user |
f |
Fields management (add/remove columns) |
s |
Change update interval |
W |
Save configuration to ~/.toprc |
Space |
Refresh immediately |
top for a specific user:
$ top -u sarah
top with a custom update interval (5 seconds):
$ top -d 5
Non-interactive batch mode (useful for logging):
$ top -b -n 1 # One iteration in batch mode
$ top -b -n 3 -d 5 > top_report.txt # 3 iterations, 5 sec apart, saved to file
htop: The Enhanced Interactive Monitor
htop is a more modern, visually richer alternative to top. It provides color-coded CPU and memory bars, mouse support, easier process management, and a more intuitive interface.
$ sudo apt install htop # Ubuntu/Debian
$ sudo dnf install htop # Fedora
$ htop
htop Interface
The top section shows horizontal bar graphs for each CPU core (color-coded: blue=low priority, green=normal, red=kernel), memory bar (green=used, blue=buffers, yellow=cache), and swap bar.
The process list shows the same information as top but with color coding and additional visual clarity.
htop Key Advantages Over top
Mouse support — click column headers to sort, click processes to select, scroll the list.
Per-core CPU display by default — shows each CPU core separately without pressing 1.
Easier process management — select multiple processes with Space, then F9 to send signals.
Tree view — press F5 to toggle between flat list and process tree view.
Search — press F3 or / to search processes by name interactively.
Better colors — visually distinguishes kernel threads, user processes, and system processes.
htop Keyboard Shortcuts
| Key | Action |
|---|---|
F1 / h |
Help |
F2 |
Setup (configure columns and display) |
F3 / / |
Search |
F4 |
Filter |
F5 |
Toggle tree view |
F6 |
Sort by column |
F7 / F8 |
Decrease/increase niceness |
F9 |
Send signal (kill, SIGTERM, etc.) |
F10 / q |
Quit |
Space |
Tag/select process |
u |
Show only specific user’s processes |
t |
Toggle tree view |
I |
Invert sort |
pgrep and pidof: Finding Processes by Name
When you know the name of a process you want to find, pgrep and pidof are faster than filtering ps output.
pgrep
pgrep searches for processes by name and returns their PIDs:
$ pgrep firefox
1523
1598
1612
Multiple PIDs indicate multiple matching processes (firefox parent and its child content processes).
Case-insensitive search:
$ pgrep -i firefox
Match against full command line (not just process name):
$ pgrep -f "python3 server.py"
2341
Show process name along with PID:
$ pgrep -la firefox
1523 firefox
1598 Web Content
1612 WebExtensions
Find processes by user:
$ pgrep -u sarah firefox
1523
Find processes NOT matching:
$ pgrep -v firefox # All PIDs except firefox
Count matching processes:
$ pgrep -c firefox
3
pidof
pidof finds PIDs for a specific program binary:
$ pidof firefox
1612 1598 1523
pidof is simpler than pgrep — it matches exactly the program name rather than accepting patterns.
pstree: Visualizing the Process Hierarchy
Every process has a parent. pstree displays processes as a tree showing parent-child relationships:
$ pstree
systemd─┬─ModemManager───2*[{ModemManager}]
├─NetworkManager───2*[{NetworkManager}]
├─accounts-daemon───2*[{accounts-daemon}]
├─dockerd─┬─containerd───11*[{containerd}]
│ └─10*[{dockerd}]
├─gdm3─┬─gdm-session-wor─┬─gdm-x-session─┬─Xorg───{Xorg}
│ │ │ └─gnome-session-b─┬─firefox─┬─Web Content─┬─...
│ │ │ │ └─{Web Content}
│ │ │ ├─nautilus───{nautilus}
│ │ │ └─gnome-terminal─┬─bash───pstree
│ │ └─{gdm-session-wor}
└─2*[{gdm3}]
Show with PIDs:
$ pstree -p
systemd(1)─┬─ModemManager(756)
├─firefox(1523)─┬─Web Content(1598)
│ └─WebExtensions(1612)
└─gnome-terminal(2100)─┬─bash(2145)
└─pstree(2901)
Show only a specific process’s tree:
$ pstree -p 1523
firefox(1523)─┬─Web Content(1598)
└─WebExtensions(1612)
Show a user’s process tree:
$ pstree -p sarah
The tree view is invaluable for understanding how processes relate to each other — particularly when a parent process is hanging and you need to know which child processes it has spawned.
Finding Resource-Hungry Processes
The Top CPU Consumers
$ ps aux --sort=-%cpu | head -10
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
sarah 1598 4.2 0.8 1234568 135280 ? Sl 09:25 1:23 Web Content
sarah 1523 2.1 1.2 2845672 201344 ? Sl 09:22 0:45 firefox
root 879 0.8 0.3 1800000 52436 ? Ssl Feb13 2:13 dockerd
The Top Memory Consumers
$ ps aux --sort=-%mem | head -10
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
sarah 1523 2.1 1.2 2845672 201344 ? Sl 09:22 0:45 firefox
sarah 1598 4.2 0.8 1234568 135280 ? Sl 09:25 1:23 Web Content
root 879 0.8 0.3 1800000 52436 ? Ssl Feb13 2:13 dockerd
Finding Zombie Processes
$ ps aux | grep 'Z'
Or:
$ ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]'
Z 1523 2901 [defunct_process] <defunct>
Zombie processes are harmless on their own — they are waiting for their parent to collect their exit status. If you have many zombies, the parent process may have a bug. Killing the parent resolves the zombies.
Watching a Process Over Time
$ watch -n 1 'ps -p 1523 -o pid,%cpu,%mem,rss,stat,cmd'
watch reruns the command every second (-n 1) and displays the updating output — a lightweight way to monitor a specific process.
/proc: The Process Information Filesystem
Every running process has a directory in /proc named after its PID. This virtual filesystem is how Linux exposes process information to commands like ps and top:
$ ls /proc/1523/
attr cgroup comm cwd environ exe fd fdinfo
maps mem mounts mountstats net ns oom_adj oom_score
pagemap root smaps stat statm status syscall task
Useful files within a process’s /proc/PID/ directory:
/proc/PID/status — human-readable process status:
$ cat /proc/1523/status
Name: firefox
Umask: 0022
State: S (sleeping)
Pid: 1523
PPid: 522
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
VmPeak: 3012456 kB
VmRSS: 201344 kB
Threads: 45
/proc/PID/cmdline — the full command that launched the process:
$ cat /proc/1523/cmdline | tr '\0' ' '
/usr/bin/firefox --new-window
/proc/PID/environ — environment variables the process was launched with:
$ cat /proc/1523/environ | tr '\0' '\n' | grep PATH
PATH=/usr/local/bin:/usr/bin:/bin
/proc/PID/fd/ — open file descriptors (files the process has open):
$ ls -la /proc/1523/fd | head -10
/proc/PID/maps — memory map showing what is loaded where:
$ cat /proc/1523/maps | head -10
This depth of process inspection is available for any process you have permission to read — which includes all your own processes, and all processes if you are root.
Practical Scenarios
Scenario 1: Identifying What Is Slowing Down the System
The system feels slow. Find the culprit:
# Check current load
$ uptime
10:35:42 up 5 days, 2:18, 2 users, load average: 11.52, 8.48, 5.45
# Load average of 11.52 on a 12-core system means near-saturation
# Find the CPU consumers
$ ps aux --sort=-%cpu | head -5
# Or use top for real-time view
$ top
In top, press P to sort by CPU. The top processes show what is consuming the most CPU right now.
Scenario 2: Checking if a Service Is Running
# Is nginx running?
$ pgrep -x nginx
3456
3457
3458
# If no output, nginx is not running
# More detail
$ ps -C nginx
PID TTY TIME CMD
3456 ? 00:00:01 nginx
3457 ? 00:00:00 nginx
3458 ? 00:00:00 nginx
-C nginx matches by exact command name.
Scenario 3: Finding All Processes of a Specific Application
# Find everything firefox has spawned
$ pstree -p $(pgrep -x firefox | head -1)
firefox(1523)─┬─{firefox}(1530)
├─{firefox}(1531)
├─Web Content(1598)─┬─{Web Content}(1599)
│ └─{Web Content}(1600)
└─WebExtensions(1612)─{WebExtensions}(1613)
Scenario 4: Monitoring a Long-Running Process
You started a backup script and want to watch its resource usage:
$ BACKUP_PID=$(pgrep -f backup.sh)
$ watch -n 5 "ps -p $BACKUP_PID -o pid,stat,%cpu,%mem,rss,etime,cmd"
Shows the backup process’s stats every 5 seconds including elapsed time.
Quick Reference: Process Viewing Commands
| Task | Command |
|---|---|
| List all processes (snapshot) | ps aux |
| Sort processes by CPU | ps aux --sort=-%cpu | head -10 |
| Sort processes by memory | ps aux --sort=-%mem | head -10 |
| Real-time process monitor | top |
| Interactive visual monitor | htop |
| Show process tree | pstree -p |
| Find PID by name | pgrep processname |
| Find PID (exact match) | pidof processname |
| Show processes by user | ps -u username |
| Show a specific process | ps -p PID |
| Count process instances | pgrep -c processname |
| Show full command line | pgrep -la processname |
| Find by full command | pgrep -f "python3 script.py" |
| Monitor one process | watch -n 1 'ps -p PID -o %cpu,%mem,rss' |
| Check process environment | cat /proc/PID/environ | tr '\0' '\n' |
| Check open files | ls -la /proc/PID/fd |
| Find zombie processes | ps aux | grep ' Z ' |
| Show process tree for PID | pstree -p PID |
| top for specific user | top -u username |
Conclusion: Processes Are the Heartbeat of Linux
Every meaningful thing happening on a Linux system is a process — a program in motion, consuming CPU and memory, reading files, communicating across the network, waiting for input. The ability to see these processes clearly, understand their resource consumption, find specific ones by name, and observe their relationships is not just a monitoring skill — it is a fundamental way of understanding what your system is doing at any moment.
The tools covered in this article form a natural progression: ps aux for quick snapshots and scripted inspection, top for real-time monitoring with broad compatibility, htop for comfortable interactive monitoring, pgrep for finding specific processes efficiently, and pstree for understanding process relationships. Behind all of these tools lies /proc — the virtual filesystem that makes all process information accessible as readable files, a design choice that perfectly reflects Linux’s philosophy of making system state inspectable and transparent.
With these tools mastered, a slow system becomes diagnosable, a misbehaving application becomes findable, and the internal life of your Linux machine becomes visible. Processes are the heartbeat of Linux — and now you know how to listen to it.




