ps takes a snapshot of running processes. Unlike top, it prints once and exits — ideal for scripts, pipes and quick answers like “is the worker running?” or “which process uses the most memory?”.
The two classic forms
ps accepts both BSD-style options (no dash) and UNIX-style options (with a dash). The two most common invocations:
ps aux # BSD style: all processes, user-oriented format
ps -ef # UNIX style: all processes, full format
ps aux output:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.3 167584 12360 ? Ss Oct23 0:41 /sbin/init
mysql 901 1.2 11.4 2501288 459012 ? Ssl Oct23 210:12 /usr/sbin/mariadbd
www-data 1402 0.4 2.1 254816 86120 ? S 09:12 0:18 php-fpm: pool www
%CPU— CPU use averaged over the process’s lifetime (not the current moment — use top for that).RSS— resident memory in KB.VSZ— virtual size (rarely meaningful).STAT— state (see below).TIME— total CPU time consumed.
ps -ef shows UID PID PPID C STIME TTY TIME CMD — notably the parent PID (PPID).
Find a process
ps aux | grep nginx
ps aux | grep '[n]ginx' # trick: excludes the grep process itself
pgrep -a nginx # PIDs and command lines
pgrep -u www-data php-fpm # by user
pidof mariadbd # PIDs of an exact program name
pgrep is cleaner for scripts:
if pgrep -x "node" > /dev/null; then echo "running"; fi
Choose your columns
ps -eo pid,ppid,user,%cpu,%mem,rss,etime,cmd
ps -o pid,etime,cmd -p 1234 # one process: how long has it been running?
ps -eo pid,lstart,cmd | grep backup # exact start time
Useful fields: pid, ppid, user, %cpu, %mem, rss, vsz, stat, etime (elapsed time), lstart (start time), nlwp (threads), ni (nice), comm (name), cmd/args (full command).
Sort
ps aux --sort=-%mem | head -10 # top memory consumers
ps aux --sort=-%cpu | head -10 # top CPU consumers (lifetime average)
ps -eo pid,rss,comm --sort=-rss | head
Memory per program, summed across processes (e.g. all PHP-FPM workers):
ps -eo rss,comm --sort=-rss | awk 'NR>1 { m[$2]+=$1 } END { for (p in m) printf "%7.0f MB %s\n", m[p]/1024, p }' | sort -rn | head
Process trees
ps -ef --forest
ps axjf
pstree -p
pstree -p $(pgrep -o php-fpm) # one subtree
Trees show who started what — a cron job spawning a runaway script, PHP-FPM’s master and its workers, a shell under sshd.
Threads
ps -eLf | grep java # one line per thread
ps -o nlwp,pid,cmd -p 1234 # number of threads of a process
ps -T -p 1234 # threads of one process
Process states (STAT)
| Code | Meaning |
|---|---|
R |
Running or runnable |
S |
Sleeping (waiting for an event) — most processes |
D |
Uninterruptible sleep — usually waiting for disk or network storage |
T |
Stopped (e.g. Ctrl+Z) |
Z |
Zombie — finished, but parent hasn’t collected its exit status |
I |
Idle kernel thread |
Extra flags: s session leader, l multi-threaded, + foreground, < high priority, N low priority.
Many processes stuck in D mean a storage problem. Zombies are harmless in small numbers but indicate a buggy parent — see zombie processes.
Processes of a user or service
ps -u www-data -o pid,%cpu,%mem,cmd
ps -fu mysql
systemctl status nginx # processes in a service's cgroup
systemd-cgls -u php8.3-fpm.service
Long-running and old processes
ps -eo pid,etimes,cmd --sort=-etimes | head # oldest first (etimes = seconds)
ps -eo pid,etimes,cmd | awk '$2 > 86400 && /php/' # PHP processes older than a day
Handy for finding hung cron jobs or forgotten scripts.
ps vs top vs htop
- ps — one snapshot; scriptable; precise columns.
- top — live, current CPU usage.
- htop — live and interactive.
Next step: acting on a process
Once you’ve found the PID, see how to kill a process — and use lsof to see which files and ports it has open.
Quick reference
| Task | Command |
|---|---|
| All processes | ps aux or ps -ef |
| Find by name | pgrep -a NAME |
| Top memory | ps aux --sort=-%mem | head |
| Custom columns | ps -eo pid,user,%cpu,%mem,cmd |
| Tree | ps -ef --forest / pstree -p |
| Threads | ps -T -p PID |
| Uptime of a process | ps -o etime= -p PID |