Processes and jobs
pgrep
Print the PIDs of processes whose name (or full command line) matches a pattern, with filters by user, parent and age.
pgrep [OPTION...] PATTERN
pgrep answers "what is the PID of that process?" without the ps aux | grep ... | grep -v grep
| awk '{print $2}' dance. It matches an extended regular expression against each process's
name, which is the program name truncated to 15 characters (what ps -o comm shows), and
prints one PID per line. With -f it matches against the whole command line instead, which is
what you need for scripts run by an interpreter (python3 app.py is named python3).
Filters narrow the match: -u by user, -P by parent PID, -n/-o newest or oldest only,
-x exact name. -l and -a add the name or command line to the output, -c counts. The exit
status is 0 if anything matched and 1 if nothing did, so pgrep -x nginx >/dev/null is a clean
"is it running?" test.
pkill is the same program with the same matching rules, sending a signal instead of printing.
Try a pattern with pgrep -a first, then swap in pkill. pgrep never lists itself, but with
-f it can match the shell or script that runs it, because that command line contains the
pattern too. The examples show this and the fixes.
Examples
Find the PIDs of a program
sleep 300 & sleep 600 &
pgrep sleep
1735 1736
One PID per line, oldest first. The pattern is a regular expression matched anywhere in the
process name, so pgrep sle would also match.
Show the command line next to each PID
sleep 300 & sleep 600 &
pgrep -a sleep
pgrep -l sleep
1738 sleep 300 1739 sleep 600 1738 sleep 1739 sleep
-a prints the full command line, -l just the process name. Use -a to check what a
pattern catches before you hand it to pkill.
Match the name exactly
sleep 300 &
pgrep -x slee; echo "slee: exit $?"
pgrep -x sleep
slee: exit 1 1742
-x requires the whole name to match, so slee finds nothing (exit status 1) and sleep
finds the process. Without -x, pgrep ssh also matches sshd and ssh-agent.
Count matching processes
sleep 300 & sleep 600 & sleep 900 &
echo "$(pgrep -c sleep) sleep processes"
3 sleep processes
-c prints the number of matches instead of the PIDs. Handy for "how many workers are
running" checks.
Test whether a program is running
sleep 300 &
if pgrep -x sleep >/dev/null; then echo "sleep is running"; fi
pgrep -x nginx >/dev/null || echo "nginx is not running"
sleep is running nginx is not running
The exit status is 0 when at least one process matched and 1 when none did, so the output
can be discarded and the test used directly in if or ||.
Match against the full command line
python3 -c 'import time; time.sleep(300)' &
sleep 0.2
pgrep -a python3
pgrep -f 'time.sleep' >/dev/null && echo "found by command line"
1 python3 /opt/runner/run.py 1754 python3 -c import time; time.sleep(300) found by command line
The process name is python3 whatever script it runs, so to find a particular script you
need -f. This sandbox's own runner is also a python3 process (PID 1), which is why
matching by name alone catches two.
Why pgrep -f can match your own shell
sleep 300 &
pgrep -af 'sleep 300'
kill %1
1758 /bin/bash -c sleep 300 & pgrep -af 'sleep 300' kill %1 1759 sleep 300
Besides the sleep, -f matched the bash -c shell running this example, because its
command line contains the text sleep 300. A script doing pkill -f myjob can kill
itself the same way. The next example shows two fixes.
Exclude your own shell from -f matches
sleep 300 &
pgrep -A -af 'sleep 300'
kill %1
1762 sleep 300
-A (--ignore-ancestors, new in procps 4) leaves out pgrep's own parent, grandparent and
so on, so the shell running the command is no longer matched. On older systems, the bracket
trick does the same job when the searching command line is not also the one that started
the process: pgrep -f '[s]leep 300' still matches sleep 300, but its own command line
contains [s]leep, which the pattern does not match.
Filter by user, newest or oldest
sleep 300 & sleep 301 & sleep 302 &
pgrep -u dev -n -a sleep
pgrep -u dev -o -a sleep
1767 sleep 302 1765 sleep 300
-u restricts to an effective user (name or UID, comma-separated). -n keeps only the
newest match and -o the oldest; both are useful when several copies run and you want the
one you just started.
Find the children of a process
(sleep 300 & sleep 400 & wait) &
sleep 0.2
pgrep -a -P $!
1772 sleep 300 1773 sleep 400
-P PPID matches processes whose parent is PPID; with no pattern it lists all of them. Here
that is the two sleep processes started by the background subshell.
Get PIDs on one line for another command
sleep 300 & sleep 600 &
pgrep -d, sleep
ps -o pid,etime,args -p "$(pgrep -d, sleep)"
1775,1776
PID ELAPSED COMMAND
1775 00:00 sleep 300
1776 00:00 sleep 600 -d, joins the PIDs with commas, which is the list format ps -p and top -p accept.
A name longer than 15 characters never matches
pgrep my-long-worker-name
pgrep: pattern that searches for process name longer than 15 characters will result in zero matches Try `pgrep -f' option to match against the complete command line.
The kernel stores only the first 15 characters of a process name, so a longer pattern can
never match by name. procps warns about it; use -f to match the command line instead.
Common pitfalls
pgrep -f patternmatching the shell or script that runs it (andpkill -fkilling it). Use-A, the[x]yzbracket trick, or a more specific pattern, and always look withpgrep -affirst.Forgetting that the pattern is an unanchored regex:
pgrep sshmatchessshd,ssh-agentandssh. Use-xfor an exact name or anchor with^ssh$.Matching scripts by name. A Python, Node or bash script's process name is the interpreter (
python3,node,bash); use-fwith the script's file name.Expecting a match for names over 15 characters. The kernel truncates
comm;pgrep -fsees the full command line.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
-ameans different things. On Linux (procps) it prints the full command line; on FreeBSD and macOS it includes pgrep's ancestors in the matches, which those systems exclude by default. To print command lines there, usepgrep -lf.The core options
-f,-l,-x,-u,-n,-o,-Pand-dwork on Linux, macOS and FreeBSD. The long--forms and procps additions such as-A,-Oand-rare Linux-only; for a portable count, pipe towc -l.
Options worth knowing
A selection, described in our own words. For the full list, see pgrep(1) or pgrep --help.
| Option | What it does |
|---|---|
-a, --list-full | Print the full command line after each PID. |
-l, --list-name | Print the process name after each PID. |
-c, --count | Print the number of matches instead of PIDs. |
-d, --delimiter STRING | Separate PIDs with STRING instead of a newline. |
-f, --full | Match the pattern against the full command line, not just the name. |
-x, --exact | Require the pattern to match the whole name (or command line with -f). |
-i, --ignore-case | Match case-insensitively. |
-v, --inverse | Select the processes that do not match. |
-n, --newest | Select only the most recently started match. |
-o, --oldest | Select only the least recently started match. |
-O, --older SECS | Select only processes running longer than SECS seconds. |
-u, --euid USERS | Match only processes with these effective users (names or IDs). |
-U, --uid USERS | Match only processes with these real user IDs. |
-G, --group GIDS | Match only processes with these real group IDs. |
-P, --parent PPIDS | Match only children of these parent PIDs. |
-g, --pgroup PGIDS | Match only processes in these process groups. |
-s, --session SIDS | Match only processes in these sessions. |
-t, --terminal TTYS | Match only processes on these terminals. |
-F, --pidfile FILE | Read the PIDs to consider from FILE. |
-r, --runstates STATES | Match only processes in these states (S, R, D, Z, ...). |
-A, --ignore-ancestors | Exclude pgrep's own ancestors (its shell) from the matches. |
-w, --lightweight | List thread IDs instead of process IDs. |
Related
pkillSend a signal (TERM by default) to every process whose name or command line matches a pattern.psPrint a snapshot of running processes, with the columns, filters and sort order you choose.killSend a signal to processes by PID or job number; by default TERM, which asks a process to exit.killallSend a signal (TERM by default) to all processes running a program with the given name.pstreeDisplay running processes as a tree, showing which process started which.grepPrint the lines of files (or standard input) that match a pattern.