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

OptionWhat it does
auxEvery process, with owner, CPU%, memory%, start time and command. The standard invocation.
-efThe System V equivalent: full listing including parent PIDs.
-u USERProcesses belonging to one user.
--sort=-%memSort by a column, e.g. memory descending.
-p PIDShow 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

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

grep

Find lines matching a pattern in files or piped input — the workhorse of text search.

head & tail

Print the first or last lines of a file — including live log following with tail -f.

kill

Terminate processes politely or forcibly — and understand what -9 really does.

Want to build real fluency? The interactive course takes you through ps and every other essential command with guided, checked exercises.