Cheat Sheet

ps Command Examples

ps prints a snapshot of the processes running right now. This sheet covers ps aux and ps -ef, what each output column means, and how to filter, sort, and format the list.

Last updated September 11, 2026

ps aux

The one most people type. BSD syntax, no leading dash: means other users' processes, adds the user-oriented columns, adds processes with no controlling terminal (daemons).

CommandWhat it does
Every process on the machine, user-oriented format
Same, one page at a time
Same, with full command lines instead of truncated ones
Only your own processes
Every process, short format (no user or memory columns)
Pick your own columns, BSD style
Only processes attached to the current terminal
The ten biggest memory users
The usual way people filter it (see grep)
Every process as a tree, with PPID and process group

ps -ef

UNIX syntax, single dash: selects every process and is the full-format listing. It is the same process list as with a different set of columns, and it is the form you will see in older scripts and on AIX, Solaris and HP-UX.

CommandWhat it does
Every process, full format
Filter it ( is cleaner)
Extra full: adds RSS, physical memory and the CPU it last ran on
Long format: priority, nice value, wait channel, state
Long format with RSS instead of address fields
Every process, PID and command only
Full command lines, no truncation at terminal width
Full format drawn as a tree
Same idea, your own columns

Flag Styles

ps accepts three different option syntaxes, and this is the single most confusing thing about it. All three work at once, which is why and both look correct and both are.

StyleLooks likeNotes
BSDNo dash. Letters stack: , , , , ,
UNIX / POSIXOne dash. , , , , , ,
GNU longTwo dashes. , , , ,

The same letter can mean different things in different styles, so the dash is not decoration:

PairDifference
vs BSD is an output format; UNIX takes a username
vs Real user (who owns it) vs effective user (whose rights it runs with)
vs BSD: drop the terminal requirement. UNIX is not a select option at all
vs asks for the processes of a user named ; procps prints a warning and usually falls back
vs Full-format columns vs the BSD forest (tree) drawing

Mixing a BSD option and a UNIX option in one command is where comes from. Pick one style per command.

Output Columns

What prints, left to right:

ColumnMeaning
The user the process runs as
Process ID, the number you pass to
CPU time used divided by how long the process has been alive, so it is a lifetime average, not what it is doing this second
RSS as a percentage of physical RAM
Virtual size in KB: everything mapped, including libraries and untouched reservations. Usually alarming and usually meaningless
Resident set size in KB: real RAM in use now. This is the number that matters
Controlling terminal. means none, which is normal for daemons; is an SSH session
Process state plus modifiers (see below)
When it started. A clock time for today, a date for anything older
Total CPU time consumed, not wall-clock age
The command line, truncated to the terminal width unless you pass

prints a different set:

ColumnMeaning
Owner, shown as a name when it fits
/ The process and its parent. Follow PPID up to find what started it
Integer CPU utilisation, a rounded and mostly obsolete version of
Start time, same idea as
Controlling terminal
Cumulative CPU time
The command line

A process with a command in square brackets, such as , is a kernel thread, not a program you installed.

STAT Codes

The first letter is the state. Anything after it is a modifier.

CodeMeaning
Running, or sitting on the run queue ready to run
Interruptible sleep, waiting for something. Most processes, most of the time
Uninterruptible sleep, almost always disk or NFS I/O. Cannot be killed, not even with
Stopped by a job control signal (Ctrl+Z, or )
Stopped by a debugger
Zombie: finished, but the parent has not read its exit status
Idle kernel thread
High priority (negative nice)
Low priority (positive nice)
Has pages locked into memory
Session leader
Multi-threaded
In the foreground process group

So is a sleeping, multi-threaded session leader, which is what a healthy daemon looks like. and a long run of are the two worth chasing.

Filter by User

CommandWhat it does
Processes running with that effective user
Same, full format
Real and effective user, BSD columns
Several users at once, comma separated
Your own processes with elapsed time
By numeric UID
Count processes per user
Everything except root's processes ( negates the selection)

Filter by PID

CommandWhat it does
One process by PID
Same, with PPID and the full command
Several PIDs, chosen columns
Just the command line, no header
How long it has been running, formatted and in seconds
The children of a process
Everything reparented to init or systemd
Every PID of a named process
Just the parent PID, handy in scripts

gives the same command line when ps is not installed.

Find by Name

CommandWhat it does
PIDs and command lines for a name (no grep, no self-match)
Match against the whole command line, not just the binary name
Everything one user runs
Select by exact command name, ps's own version of the same thing
Exact name, with columns
PIDs only, ready to pipe into
The bracket trick, so grep does not match itself
Kill by pattern ( first to check what it matches)
All PIDs of a binary on one line

For a service you manage with systemd, shows the same PIDs plus the unit state and recent logs. See systemctl and journalctl.

Sort by Memory and CPU

takes a column key. A leading sorts descending, or nothing sorts ascending.

CommandWhat it does
Top ten memory users (line 1 is the header)
Top ten by lifetime average CPU
Same by real RSS, in a tighter format
The longest-running processes
The most recently started
Two keys, in order
# Memory used per program name, biggest first
ps -eo comm,rss --no-headers | awk '{m[$1]+=$2} END {for (c in m) printf "%8.1f MB  %s\n", m[c]/1024, c}' | sort -rn | head

Remember that in ps is an average over the life of the process. A process that pinned a core for an hour last night still ranks high, and one spiking right now may not. For live CPU, use top or htop.

Custom Format

(or for every process) replaces the default columns with exactly the ones you ask for.

CommandWhat it does
A practical default
Binary name only (15 chars max)
The full command line with arguments
What a stuck process is waiting on
Exact start date and time, not the abbreviated
Nice value and priority
Drop the header row, for scripts
Widen one column to 120 characters
Rename headers with
One value, no header, ready for a variable
The four user identities of a process

Common keys: , , , , , , , , , , , , , , , , , , , , , . prints the whole list.

Threads

CommandWhat it does
Every thread on the machine, with (thread ID) and (thread count)
The threads of one process
How many threads it has, as a bare number
The busiest threads
Threads with an column
Scheduling class and realtime priority per thread

A thread's or is the number and show when you turn threads on, so you can match one to the other.

Process Tree

CommandWhat it does
Full listing drawn as a tree
BSD version, with PPID, PGID and session
One user's processes as a tree
Tree with your own columns
Hierarchy by indentation instead of line drawing
The dedicated tool, with PIDs
The ancestry of one PID, up to init

ps vs top

Question /
What it gives youOne snapshot, then exitsA live view that refreshes
meansAverage over the whole life of the processUsage during the last refresh interval
ScriptingBuilt for it: , , exact fieldsNeeds and parsing
Sorting on any columnInteractive keys, or in top
Killing a processRead the PID, then Press (top) or (htop)
Best forFinding a PID, scripts, an exact column setWatching load as it happens

Rule of thumb: answers "what is running and what is its PID", answers "what is eating the machine right now". Full keys and columns are on the top and htop sheet.

Gotchas

  • and are both right. is not: it asks for a user named , and only works because procps guesses what you meant and warns you.
  • Mixing styles in one command gives . is fine because GNU long options combine with either style, but is not.
  • is a lifetime average. Sorting by it finds yesterday's hog, not today's.
  • Summing the column overcounts, because shared libraries are charged in full to every process that maps them.
  • A state process ignores every signal including . It is stuck in the kernel, usually on disk or NFS, and only unblocks when the I/O finishes or the machine reboots.
  • Output is truncated to terminal width. Add (, ) before deciding a command line looks wrong.
  • always matches its own grep. Use or .
  • is a different command with different flags. It lists containers, not processes; is the one that lists processes inside a container. See the docker sheet.
  • A minimal container image has no at all. Install , or run from the host.
  • To find which process owns a port, ps is the wrong tool. Use or , covered on the netstat and ss sheet.

ps FAQ

What is the difference between ps aux and ps -ef?

They list the same processes in different formats. ps aux is BSD syntax and gives you %CPU, %MEM, VSZ, RSS, STAT and START, which is what you want when you are hunting a memory or CPU hog. ps -ef is UNIX syntax and gives you PPID and STIME instead, which is what you want when you care about which process started which. Both truncate the command to your terminal width, so add ww to either one when the line matters. Use whichever you like; just do not write ps -aux, which asks for processes owned by a user named x.

What do VSZ and RSS mean in ps output?

VSZ is virtual size: every byte the process has mapped, including shared libraries, files mapped into memory and memory it reserved but never touched. It is usually huge and almost never the number you want. RSS is resident set size: the physical RAM the process actually occupies right now, in kilobytes. RSS is the useful one, with one catch. Shared libraries count in full against every process that maps them, so adding up the RSS column gives a total larger than the memory in the machine. For a per-process figure that splits shared pages fairly, read /proc/PID/smaps_rollup or install smem.

Why does ps cut off the end of the command?

ps truncates each line to the width of your terminal. Add w to widen it and ww for unlimited width: ps auxww or ps -efww. The GNU form is --width 200 or --cols 200. If you only need one process, ps -p 1234 -o args= prints the full command line with no header and no truncation. Piping into less -S also works, and lets you scroll sideways with the arrow keys.

How do I find zombie or defunct processes with ps?

Zombies carry the state code Z and show as <defunct> in the command column. List them with ps -eo pid,ppid,stat,cmd | awk '$3 ~ /^Z/'. You cannot kill a zombie, because it is already dead: it is a finished process whose exit status the parent never collected. Look at the PPID column instead and deal with the parent, either by sending it SIGCHLD or by restarting it. A handful of short-lived zombies is normal; hundreds mean a buggy parent.

Why is ps command not found inside a Docker container?

Slim base images ship without procps, the package that contains ps. Install it with apt-get update && apt-get install -y procps on Debian and Ubuntu images, apk add procps on Alpine, or microdnf install procps-ng on UBI. You often do not need to: docker top CONTAINER lists a container's processes from the host, and ps -ef on the host shows them too, with the host's PID numbers rather than the container's.

Related cheat sheets