The ps command in Linux
ps (process status) takes a snapshot of running processes. Its everyday job is answering two questions: "is X running?" and "what is its PID?" — the number you need to feed kill. The syntax has two historical dialects; in practice everyone types ps aux and filters with grep.
How ps works
ps has no privileged channel into the kernel — it reads /proc, the virtual filesystem where the kernel publishes a numbered directory per process. The columns of ps aux are files you can cat yourself: /proc/PID/stat and status hold state and memory, /proc/PID/cmdline the arguments. ps is a formatter over a filesystem, which is the "everything is a file" philosophy in its purest form.
The %CPU column deserves a caveat: it is the ratio of CPU time consumed to elapsed lifetime — an average since launch, not the current instant (top measures deltas between refreshes, which is why they disagree). The bracketed names ([kworker/0:1]) are kernel threads with no user-space command line. And a Z in STAT marks a zombie: a process that has already exited and whose corpse — the exit status — merely awaits collection by its parent; you cannot kill what is already dead.
Syntax
ps [OPTIONS] Common options
| Option | What it does |
|---|---|
aux | Every process, with owner, CPU%, memory%, start time and command. The standard invocation. |
-ef | The System V equivalent: full listing including parent PIDs. |
-u USER | Processes belonging to one user. |
--sort=-%mem | Sort by a column, e.g. memory descending. |
-p PID | Show a specific process. |
How to use ps: examples
$ ps aux The full table: USER, PID, %CPU, %MEM, START and COMMAND for everything running.
$ ps aux | grep nginx Is nginx running, and with what PID? (The grep itself appears in the results — a famous quirk.)
$ ps aux --sort=-%mem | head -n 10 The ten most memory-hungry processes.
$ ps -u www-data Everything running as the www-data user.
$ ps -ef | grep python Same hunt, System V style — includes the parent PID column, useful for tracing who launched what.
Real-world use cases for ps
Finding a runaway process
The fans spin up: ps aux --sort=-%cpu | head -5 names the culprit with its PID in one line. The memory variant (--sort=-%mem) answers the "why is everything swapping?" morning just as fast.
Verifying a service really runs
Deploy scripts and health checks confirm liveness with pgrep -f "gunicorn.*myapp" — exit code 0 means running. Cleaner than the ps | grep dance, and no self-matching to filter out.
Pro tips and common mistakes
- ps aux | grep name matches its own grep; the classic filter is grep [n]ame — or just use pgrep.
- See a process's full command line, unabridged: ps -fp PID -ww (double w disables truncation).
- The STAT column tells stories: Z is a zombie, D is stuck on I/O (the state that ignores kill -9), T is stopped.
- Tree view — who spawned whom: ps -ef --forest, or the friendlier pstree.
Frequently asked questions about ps
What do the columns of ps aux mean?
USER owns the process; PID is its ID; %CPU and %MEM are current usage; VSZ/RSS are virtual and resident memory; START is launch time; COMMAND is the program with its arguments.
Why does "ps aux | grep foo" show the grep itself?
Because the grep process was already running (with "foo" in its command line) when ps took the snapshot. Filter it out with grep -v grep, or use pgrep foo instead.
What is the difference between ps and top?
ps prints a one-off snapshot, ideal for scripts and pipes; top (or htop) is an interactive live view that refreshes continuously.
Related commands
Find lines matching a pattern in files or piped input — the workhorse of text search.
head & tailPrint the first or last lines of a file — including live log following with tail -f.
killTerminate processes politely or forcibly — and understand what -9 really does.