How to Monitor Processes on Linux
Learn to monitor Linux processes with ps, top, htop, and btop. Covers reading process states, killing processes safely, and tuning CPU priority with nice/renice.
Before you start
- ▸Terminal access (local or SSH)
- ▸sudo privileges for installing packages and raising process priority
- ▸Basic familiarity with navigating the Linux command line
Linux gives you several layers of visibility into running processes—from quick one-liners to full interactive dashboards. Knowing which tool to reach for, and how to act on what you see, is a daily skill for anyone managing Linux systems. This guide walks through the most useful utilities in order of complexity, then covers how to kill misbehaving processes and adjust their CPU priority.
Understanding Process States
Before firing up any tool, know what you're reading. Every process carries a single-character state code:
- R – Running or runnable (on the CPU or waiting for a CPU slot)
- S – Interruptible sleep (waiting for an event, e.g. I/O or a timer)
- D – Uninterruptible sleep (usually stuck in a kernel I/O call; worrying if persistent)
- Z – Zombie (process finished but parent hasn't collected its exit code)
- T – Stopped (paused with SIGSTOP or Ctrl-Z)
- I – Idle kernel thread (normal; seen in
psoutput for kernel workers)
A handful of D-state processes during heavy disk activity is normal. Many of them, or a persistent zombie count, signals a problem worth investigating.
Snapshot Monitoring with ps
ps prints a static snapshot of the process table. It reads /proc directly and exits immediately—useful in scripts and quick checks.
Common ps invocations
Show every process on the system in a readable format:
ps aux
The columns that matter most: %CPU, %MEM, STAT (process state), and COMMAND.
BSD-style (aux) and UNIX-style (-ef) are both widely supported. To see full command lines including arguments:
ps -ef
Filter to a specific process name without involving grep:
ps -C nginx
Show a process tree (who spawned what):
ps axjf
Sort by memory consumption, showing the top 10 consumers:
ps aux --sort=-%mem | head -11
Real-Time Monitoring with top
top is installed on virtually every Linux system and needs no extra packages. It refreshes every 3 seconds by default and shows system-wide CPU, memory, and swap summaries at the top, followed by a live process list.
top
Key interactive commands inside top:
- P – Sort by CPU usage (default)
- M – Sort by memory usage
- k – Kill a process (prompts for PID and signal)
- r – Renice a process (change its priority)
- 1 – Toggle per-CPU breakdown
- q – Quit
Run top non-interactively for a single batch snapshot—handy in scripts:
top -b -n 1 | head -20
Interactive Monitoring with htop
htop is top with a modern ncurses interface: colour-coded CPU/memory meters per core, mouse support, and intuitive keybindings. Install it first if needed.
Install htop
# Debian / Ubuntu
sudo apt install htop
# Fedora / RHEL / Rocky
sudo dnf install htop
# Arch
sudo pacman -S htop
htop
Useful htop keybindings:
- F6 or > – Choose sort column
- F4 – Filter processes by name substring
- F5 – Toggle tree view (shows parent/child relationships)
- F9 – Send a signal to the selected process
- Space – Tag a process; tagged processes can be acted on in bulk
- u – Filter by a specific user
htop also shows individual thread counts and integrates lsof/strace shortcuts if those tools are installed.
Rich Monitoring with btop
btop (formerly bpytop) takes the dashboard concept further: GPU support (with optional plugin), network and disk I/O graphs, and a responsive layout that adapts to terminal size. It's the right choice when you want a persistent monitoring pane during troubleshooting sessions.
Install btop
# Debian / Ubuntu 22.04+
sudo apt install btop
# Fedora 37+
sudo dnf install btop
# Arch
sudo pacman -S btop
On older releases without a packaged version, grab a static binary from the btop GitHub releases page and place it in /usr/local/bin.
btop
Inside btop, press ? for a full keybinding reference. The process panel supports the same filter (f) and kill (k) workflow as htop.
Finding a Process by Name or Port
When you know the name but not the PID:
pgrep -la nginx
Output is PID followed by the full command — -a shows the command line, -l the name. Output will vary by what's running.
To find what process owns a listening port (requires ss, part of iproute2):
sudo ss -tlnp | grep ':80'
Killing and Signalling Processes
Processes communicate through signals. The most common:
| Signal | Number | Meaning |
|---|---|---|
| SIGTERM | 15 | Politely ask the process to exit (default for kill) |
| SIGKILL | 9 | Force-terminate immediately; process cannot catch or ignore this |
| SIGHUP | 1 | Reload configuration (convention; behaviour is process-defined) |
| SIGSTOP | 19 | Pause the process (like Ctrl-Z from a terminal) |
| SIGCONT | 18 | Resume a stopped process |
Always try SIGTERM first. SIGKILL skips cleanup routines and can leave lock files or corrupt data.
# Graceful termination by PID
kill 1234
# Force-kill only if SIGTERM didn't work
kill -9 1234
# Kill all processes matching a name (careful with this)
pkill -TERM nginx
# Kill all processes matching a name, owned by a specific user
pkill -u www-data php-fpm
Adjusting Process Priority with nice and renice
Linux schedules CPU time partly based on a process's nice value, which ranges from -20 (highest priority) to +19 (lowest). Regular users can only lower priority (increase the nice value); root can raise it.
Start a new command with a lower priority so it doesn't compete with interactive work:
nice -n 15 tar -czf backup.tar.gz /home/user/data
Adjust the priority of an already-running process by PID:
# Lower priority (any user, for their own processes)
renice +10 -p 5678
# Raise priority (requires root)
sudo renice -5 -p 5678
In htop, select a process and press F7/F8 to decrement/increment nice value interactively.
Verifying What You See
Cross-check a suspicious process directly through /proc. Every PID has a directory there:
# Confirm the exact command line of PID 1234
cat /proc/1234/cmdline | tr '\0' ' '
# Check which user owns it
ls -l /proc/1234 | head -3
# See open file descriptors
ls -l /proc/1234/fd
Troubleshooting Common Issues
Process stuck in D state
Uninterruptible sleep almost always means the process is waiting on a kernel call—usually disk or NFS I/O. You cannot SIGKILL a process in D state; the kernel must release it. Check dmesg and your storage subsystem for I/O errors.
Zombie processes
Zombies are harmless individually—they consume only a PID slot—but if their count grows, the parent process has a bug. You cannot kill a zombie directly; killing or signalling its parent (SIGCHLD prompts a wait() call) will reap it. If the parent is systemd or PID 1, a reboot is the practical fix.
htop shows 100% CPU on one core constantly
Sort by CPU (P in top, or click the CPU% column in htop) and note the process name. Use strace -p PID to see what system calls it's making, or check its logs via journalctl -u servicename if it's a systemd unit.
Frequently asked questions
- What is the difference between ps aux and ps -ef?
- Both show all processes system-wide, but `ps aux` uses BSD syntax and includes a %CPU/%MEM column, while `ps -ef` uses UNIX syntax and adds the parent PID (PPID) column. The output is equivalent for most everyday use.
- Why can't I kill a process even with kill -9?
- SIGKILL cannot be caught or ignored, but it also cannot preempt a process stuck in uninterruptible sleep (D state). The kernel must release the process from its blocked I/O call first. Check for storage or NFS errors with `dmesg`.
- What does a high nice value actually do?
- A high nice value (e.g. +15 or +19) tells the Linux CFS scheduler to favour other processes over this one when CPU time is contested. The process still runs at full speed when the CPU is idle; the nice value only matters under load.
- Is htop better than top for everyday use?
- htop is more ergonomic—colour meters, mouse support, and tree view make it faster to use interactively. However, top ships on virtually every Linux installation without extra packages, so knowing top remains important for working on minimal or locked-down systems.
- How do I find which process is listening on a specific port?
- Run `sudo ss -tlnp | grep ':<port>'`. The output includes the PID and process name in the last column. You can then look up that PID in htop or with `ps -p PID`.
Related guides
Bash Arrays and Associative Arrays
Master bash indexed and associative arrays: declaration, element access, looping, mapfile, namerefs, and practical patterns for real scripting work.
Bash Functions and Variable Scoping
Master Bash function scoping with local variables, source-based libraries, correct use of return codes, and array passing techniques including namerefs.
Bash Loops: for, while and until
Learn all three Bash loop types — for, while, and until — with practical, copy-paste examples covering file iteration, counting, polling, and safe line reading.
Bash Scripting for Beginners
Learn Bash scripting from scratch: shebang lines, variables, conditionals, loops, and arguments, plus a real backup script to tie it all together.