Knowing how to find and manage processes is fundamental sysadmin work. It’s not glamorous, but it comes up constantly — debugging a runaway process eating CPU, finding what’s holding a port open, or tracing which process opened a particular file.
ps: The Process Snapshot
ps shows a snapshot of current processes. The options are confusing because there are two syntaxes: BSD-style (no dash) and Unix-style (with dash). I mostly use these:
ps aux # All processes, BSD format
ps -ef # All processes, Unix format
ps aux output columns: USER, PID, %CPU, %MEM, VSZ (virtual memory KB), RSS (real memory KB), TTY, STAT, START, TIME, COMMAND.
Common ps patterns:
# Find a process by name
ps aux | grep nginx
# Show only your own processes
ps u
# Show process tree (parent-child relationships)
ps auxf
# or
ps -ejH
# Show processes sorted by CPU usage
ps aux --sort=-%cpu | head -20
# Show processes sorted by memory usage
ps aux --sort=-%mem | head -20
# Show specific columns
ps -eo pid,ppid,user,%cpu,%mem,cmd --sort=-%cpu | head -20
STAT codes: S = sleeping, R = running, Z = zombie, T = stopped, D = uninterruptible sleep (usually I/O), < = high priority, N = low priority.
Zombie processes (Z) are dead but not yet reaped by their parent. A few are normal; many indicate a poorly written parent process.
pgrep and pkill
Better than ps aux | grep:
# Find PIDs matching a name
pgrep nginx
pgrep -u www-data nginx # Only processes owned by www-data
# List process names matching pattern
pgrep -la php
# Kill processes matching a name
pkill nginx # Sends SIGTERM by default
pkill -9 nginx # Force kill (SIGKILL)
pkill -HUP nginx # Send SIGHUP (reload)
pkill -u apache httpd # Kill httpd processes owned by apache
pkill is useful but dangerous — be specific about the pattern or you might kill the wrong thing.
top: Live Process Monitoring
top
Default top view: processes sorted by CPU. Key interactive commands:
M— sort by memoryP— sort by CPU (default)k— kill a process (prompts for PID and signal)r— renice a process (change priority)1— show per-CPU statsH— toggle showing threadsq— quit
Top header line stats:
load average: 0.52, 0.41, 0.38
The three numbers are load average for 1 minute, 5 minutes, 15 minutes. Load average of 1.0 on a single-core system means fully utilized. On a 4-core system, 4.0 means fully utilized. Values above the core count mean processes are queuing.
htop: Interactive Process Manager
htop is top with a better interface:
apt install htop
htop
htop shows CPU bars, memory, swap graphically. You can scroll horizontally to see full command lines, filter processes, and tree view is built in. Mouse support works too.
Press F1 for help, F2 for setup, F3 to search, F5 for tree view, F9 to kill.
I use htop most often when I need to understand what’s happening on a busy server visually. For scripting or quick checks, ps is faster.
Finding What’s Using a Port
# What's listening on port 80?
ss -tlnp | grep :80
# or
lsof -i :80
# or
fuser 80/tcp
ss (socket statistics) is the modern replacement for netstat:
ss -tlnp # TCP, listening, numeric, with process info
ss -ulnp # UDP version
ss -tnp # Connected TCP connections
ss -s # Summary
Find all listening ports:
ss -tlnp | grep LISTEN
lsof: What Files/Sockets a Process Has Open
lsof (list open files) shows everything a process has open — files, sockets, pipes:
# Files opened by a specific process
lsof -p 1234
# Processes that have a specific file open
lsof /var/log/nginx/error.log
# Network connections for a process
lsof -p 1234 -i
# Files under a directory
lsof +D /var/log
# All network connections
lsof -i
# Processes using a specific port
lsof -i :443
The deleted-but-open file case I mentioned earlier:
lsof +L1 # Files with link count < 1 (deleted but open)
Signals
Processes communicate through signals. The common ones:
kill -SIGTERM pid # Polite termination request (process can clean up)
kill -SIGKILL pid # Force kill, unblockable
kill -SIGHUP pid # Reload configuration (for daemons)
kill -SIGUSR1 pid # User-defined (often log rotation signal)
kill -SIGSTOP pid # Pause a process
kill -SIGCONT pid # Resume a paused process
Numbers: SIGTERM=15, SIGKILL=9, SIGHUP=1.
kill -9 is the nuclear option. Try SIGTERM first — it lets the process clean up gracefully. SIGKILL should be used when SIGTERM doesn’t work.
# Send SIGTERM, wait, then SIGKILL if needed
kill -TERM 1234
sleep 10
kill -0 1234 && kill -KILL 1234 # -0 checks if process exists
Limiting CPU/Memory
For long-running tasks that should be low-priority:
# Run a command with low priority (nice value 19 = lowest)
nice -n 19 /usr/local/bin/backup.sh
# Change priority of running process
renice 10 -p 1234 # Set nice value to 10
Nice values: -20 (highest priority) to 19 (lowest). Regular users can only set positive nice values (lower priority). Root can set negative values.
cpulimit is another option for hard CPU percentage limits:
apt install cpulimit
cpulimit -p 1234 -l 25 # Limit PID 1234 to 25% CPU
Or use cgroups for resource limits in systemd services:
[Service]
CPUQuota=50%
MemoryLimit=512M
Zombie Process Cleanup
Zombies can’t be killed directly — they’re already dead. The parent process needs to call wait() to clean them up.
ps aux | grep 'Z' # Find zombies
Find the parent:
ps -o ppid= -p zombie_pid
If the parent is hanging, sending SIGCHLD to the parent often triggers cleanup:
kill -SIGCHLD parent_pid
If that doesn’t work, killing the parent clears the zombie (it gets adopted by init, which cleans it up).
Useful Combinations
Find which process is hitting the CPU hardest, log it, and notify:
#!/bin/bash
# Log top CPU process every minute
TOP=$(ps aux --sort=-%cpu | head -2 | tail -1)
echo "$(date): $TOP" >> /var/log/top-cpu.log
CPU=$(echo "$TOP" | awk '{print $3}')
if (( $(echo "$CPU > 90" | bc -l) )); then
echo "$TOP" | mail -s "High CPU process on $(hostname)" you@example.com
fi
Combine with a cron job for continuous monitoring without installing dedicated tools.
For services that should stay running, use systemd with Restart=on-failure rather than monitoring and restarting manually. If you’re manually restarting things with scripts, convert those to proper systemd services.