When you need to know which PID owns a stuck job, who is running a binary, or whether a script path is still alive, a one-shot process query beats a full-screen monitor. That is what ps and pgrep are for. ps prints a snapshot table you can read, sort, and paste into a ticket. pgrep returns matching PIDs (and optionally names) for scripts and pipelines.

Live dashboards belong elsewhere: top, htop, and btop watch CPU and RAM as they change. This article owns the query side — find a process by PID, user, memory footprint, or execution path, then move on.

Warm-up: your shell and a decoy process

Start with two known PIDs: your current shell, and a harmless background decoy you can hunt and remove.

Print your shell’s PID ($$ expands inside the shell):

echo $$

Start a decoy that will sit quietly for a few minutes, and note the PID the shell prints:

sleep 300 &

Inspect that PID with ps (replace 12345 with the number you saw):

ps -p 12345

Typical output:

  PID TTY          TIME CMD
12345 pts/0    00:00:00 sleep

When you are done practicing, clean up the decoy:

kill 12345

Note: If you forgot the PID, pgrep sleep (covered below) finds it again. Prefer killing only the decoy you started — not every sleep on a shared host.

Everyday snapshots

Two classic forms show almost every process. They differ mainly in column layout and heritage; both are fine for triage.

BSD-style snapshot (wide, includes %CPU and %MEM):

ps aux

System V-style snapshot (UID, PID, PPID, CMD):

ps -ef

Sample ps aux columns to read with intent:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
alice    12345  0.0  0.0   8900   720 pts/0    S    00:10   0:00 sleep 300
alice     2201  0.2  1.4 450000 56000 ?        Ssl  Jan04   3:12 /usr/bin/node server.js

USER and PID answer ownership. %MEM / RSS hint at memory weight. COMMAND / CMD is the short name or path — often truncated in the default width.

Note: Pipe to less or head when the list is huge. A full ps aux on a busy host is a firehose; filter as soon as you know a name, user, or PID.

Find PIDs with pgrep

When you only need “which PIDs match this name?”, pgrep is cleaner than ps | grep. It does not match its own grep line the way a naive pipeline can.

Find PIDs whose process name matches sleep:

pgrep sleep

Show PID and name:

pgrep -l sleep

Show PID and the full command line:

pgrep -a sleep

Typical -a output for the decoy:

12345 sleep 300

Compare with a fragile pipeline that often matches itself:

ps aux | grep sleep

Note: Prefer pgrep for name → PID. Use ps when you need CPU, memory, state, or custom columns in the same view.

Filter by user

On shared machines, limit the view to one account before you hunt by name.

Processes for a given user with ps:

ps -u alice

Same idea with pgrep (prints PIDs owned by that user; combine with a name pattern):

pgrep -u alice
pgrep -u alice sleep

For your own processes only:

ps -u "$USER"
pgrep -u "$USER" -a .

Note: -u on pgrep without a pattern lists every PID for that user. Add a name when you already know what you are hunting.

Rank by memory or CPU

Snapshots can answer “who is heavy right now?” without opening a monitor. Sort descending by memory or CPU and keep the top rows.

Highest memory first:

ps aux --sort=-%mem | head -n 15

Highest CPU first:

ps aux --sort=-%cpu | head -n 15

Note: These numbers are a moment in time. If the hot process changes every second, switch to top/htop for a live sort. Use ps --sort for a pasteable snapshot in a ticket or chat.

Full command and execution path

Default CMD columns often truncate. Ask for the full argument vector when you need the script path, config flag, or which copy of a binary is running.

Show full args for one PID:

ps -p 12345 -o pid,user,args

args and cmd both expand the command line; args is the usual choice in custom formats.

Match against the full command line with pgrep -f (not just the process name). Useful when many workers share a name but differ by path or flags:

pgrep -af 'node.*server.js'
pgrep -af '/usr/bin/python3.*/opt/app/'

Note: -f is powerful and easy to over-match. Anchor on a distinctive path or flag. Test with -a (list) before you pipe PIDs into anything destructive.

Custom columns

Build a ticket-friendly table with only the fields you care about. -o selects columns; comma-separated names define the row.

ps -eo pid,ppid,user,%mem,rss,stat,args --sort=-rss | head -n 20

Read RSS (resident set, kilobytes) as a concrete memory footprint; %MEM as a share of machine RAM. STAT letters encode state (R running, S sleeping, Z zombie, and more). PPID is the parent — useful when a reaper or supervisor owns a flock of workers.

For a single PID in the same shape:

ps -p 12345 -o pid,ppid,user,%mem,rss,stat,args

Note: Keep a short -o list you like and reuse it. Wide default dumps waste time; custom columns make the next paste readable.

Trees and parents

When dozens of workers share a name, parent/child structure clarifies which tree to restart.

Forest view (ASCII tree):

ps -ef --forest

Or hierarchical formatting:

ps -efH

Scroll to your service’s parent PID, then confirm children with pgrep or ps --ppid:

ps --ppid 2200 -o pid,user,args

Note: Reach for a forest view when “kill one worker” might be wrong and you need the supervisor PID instead. For open files or ports held by that PID, continue with lsof.

Quick reference card

Keep this nearby until the flags become muscle memory:

GoalCommand
One PIDps -p PID
All processes (BSD)ps aux
All processes (SysV)ps -ef
PIDs by namepgrep name
Name + cmdlinepgrep -a name
Full cmdline matchpgrep -af 'pattern'
By userps -u user / pgrep -u user
Top memoryps aux --sort=-%mem | head
Top CPUps aux --sort=-%cpu | head
Custom columnsps -eo pid,user,%mem,rss,args
Full args for PIDps -p PID -o pid,user,args
Process treeps -ef --forest

Practice drills

Use your own shell and a fresh sleep 300 & decoy. Try these without peeking.

  1. Print your shell’s PID, then show a one-line ps view for it with user and full args.
  2. Find the decoy with pgrep so the full command line is visible.
  3. List the ten highest-memory processes on the box.
  4. Show custom columns (pid, user, %mem, rss, args) for the decoy’s PID.
  5. Use pgrep -f to match a distinctive substring of a real process’s path or args on your system (for example bash or ssh).

When you are ready to compare, here are solid answers — not the only ones, but clear and portable:

ps -p $$ -o pid,user,args
pgrep -a sleep
ps aux --sort=-%mem | head -n 11
ps -p "$(pgrep -n sleep)" -o pid,user,%mem,rss,args
pgrep -af ssh

Clean up when finished (newest sleep only — be careful on shared hosts):

kill "$(pgrep -n sleep)"

If you can work through those five comfortably, you already cover most real ps / pgrep work: identify a PID, filter by name or user, rank by memory, read full command lines, and hand off to a live monitor only when the snapshot is not enough. Query with ps and pgrep; watch with top/htop/btop when the machine is still moving under you.