pgrep Command: Finding a PID by Name, the -f Option, and How pidof and pkill Differ

Test environmentRHEL familyAlmaLinux 9.8procps-ng 3.3root accountDebian 12 · procps-ng 4.0.2 regular account
Process · job scheduling commandspgrep, pidofLocation/usr/bin/pgrep

To find the number (PID) of a running process by its name, account, or command line, use the pgrep command. On an AlmaLinux 9 server, we copied the sleep program under different names, started three of them, and compared the processes each option found. Searching by name returned only those three processes, while searching the whole command line with -f also returned the timeout that launched them.

The output below comes from the root account on an AlmaLinux 9.8 server and a regular account on a Debian 12 server. The targets were copies of sleep named pgdemo-a and pgdemo-b, started with timeout 300 so they would exit on their own after 5 minutes. Process numbers (PIDs) and the Debian account name (user1) were replaced with example values, and the procps-ng version on the AlmaLinux server is shown only up to the major and minor version.

1️⃣ Basic pgrep Command Usage

  • ↪️ Finding a PID by Name and the Exit Code

If you write part of a name after pgrep, it prints the numbers of the processes whose names contain those characters, one per line. Searching for pgdemo returned three numbers: two pgdemo-a processes and one pgdemo-b.

pgrep pgdemo
2143
2152
2155

Writing the name up to pgdemo-a left only the two pgdemo-a processes.

pgrep pgdemo-a
2143
2152

The search text is read as an extended regular expression, and without options pgrep looks only at process names.

When no process matches, pgrep prints nothing and exits, so check the result with the exit code. After searching for the nonexistent name pgdemo-zz, running [echo $?] returned 1.

pgrep pgdemo-zz
echo $?
1

Running it without any criteria produced the error below and exit code 2. The man page describes the exit codes as 0 (found), 1 (not found), 2 (command-line syntax error), and 3 (fatal error such as running out of memory).

pgrep
pgrep: no matching criteria specified
Try `pgrep --help' for more information.
echo $?
2

By using this exit code as a condition instead of the output, a script can check whether a process is running. Check the version with [pgrep -V]. The Debian 12 server had procps-ng 4.0.2, and the AlmaLinux 9.8 server had procps-ng 3.3.

pgrep -V
pgrep from procps-ng 4.0.2

2️⃣ The pgrep -f Option and -l, -a Output

  • ↪️ Processes That Also Match the Whole Command Line

The number alone does not tell you which process it is, so print the name with -l or the whole command line with -a.

pgrep -l pgdemo
2143 pgdemo-a
2152 pgdemo-a
2155 pgdemo-b
pgrep -a pgdemo
2143 ./pgdemo-a 300
2152 ./pgdemo-a 301
2155 ./pgdemo-b 300

The 300 and 301 at the end of the -a output are the arguments in seconds passed to sleep. These arguments told the two pgdemo-a processes with the same name apart.

With -f, pgrep searches the whole command line instead of the name. Searching for pgdemo-a with -f raised the count from two numbers to four.

pgrep -f pgdemo-a
2141
2143
2150
2152

Adding -a showed that the two extra lines were the timeout processes that received pgdemo-a as an argument. Their name is timeout, but their command line contains pgdemo-a, so they matched -f.

pgrep -af pgdemo-a
2141 timeout 300 ./pgdemo-a 300
2143 ./pgdemo-a 300
2150 timeout 300 ./pgdemo-a 301
2152 ./pgdemo-a 301

When you use -f inside a script, check whether the script itself shows up in the results. pgrep never includes itself in the results, but if the command line of the script that ran pgrep contains the search text, that script is listed too.

Searching for pgdemo-a with chk.sh, a script that passes its argument straight to [pgrep -af], added bash chk.sh pgdemo-a, the script itself, as the last line.

bash chk.sh pgdemo-a
2141 timeout 300 ./pgdemo-a 300
2143 ./pgdemo-a 300
2150 timeout 300 ./pgdemo-a 301
2152 ./pgdemo-a 301
2160 bash chk.sh pgdemo-a

The pattern [p]gdemo-a, which wraps the first letter in brackets, matches the same text as pgdemo-a as a regular expression, but the script's command line contains the brackets literally, so it no longer matches. Passing this pattern to the same script dropped the script line and left only four lines.

bash chk.sh '[p]gdemo-a'
2141 timeout 300 ./pgdemo-a 300
2143 ./pgdemo-a 300
2150 timeout 300 ./pgdemo-a 301
2152 ./pgdemo-a 301

3️⃣ pgrep Matching Options

  • ↪️ -u for Account, -x for Exact Name, -n and -o, -c for Count

With -x, pgrep finds only processes whose whole name matches, not part of it. Searching for pgdemo returned nothing, while searching for pgdemo-a returned two.

pgrep -x pgdemo
pgrep -lx pgdemo-a
2143 pgdemo-a
2152 pgdemo-a

-u selects processes by the account that started them. If you list several accounts separated by commas, it finds every process that belongs to any one of them. The three processes started as root all appeared with [-u root], and [-u daemon] returned none.

pgrep -u root -l pgdemo
2143 pgdemo-a
2152 pgdemo-a
2155 pgdemo-b
pgrep -u daemon -l pgdemo
pgrep -u root,daemon -c pgdemo
3

Giving an account that does not exist produced the [invalid user name] error and exit code 2.

pgrep -u no-such-user9 pgdemo
pgrep: invalid user name: no-such-user9

On the Debian 12 server, a regular account also found the single sleep it had started under its own account with the same options.

pgrep -u user1 -l sleep
3047 sleep
pgrep -u user1 -a sleep
3047 sleep 60

When several processes share a name, -n prints only the most recently started one and -o only the oldest one. Of two pgdemo-a processes started 2 seconds apart, -n picked the later one and -o the earlier one.

pgrep -n pgdemo-a
2152
pgrep -o pgdemo-a
2143

The man page says -n and -o cannot be used together. Giving both printed only the usage text, with no error message.

-c prints a count instead of numbers. When nothing matched, it printed 0 and the exit code was 1.

pgrep -c pgdemo
3
pgrep -c pgdemo-zz
0

Here is a summary of the pgrep options.

OptionCopyDescription
-f--fullSearch the whole command line instead of the name
-l--list-namePrint the name along with the number
-a--list-fullPrint the whole command line along with the number
-x--exactFind only processes whose whole name matches
-u--euidOnly processes started by the given account; with several separated by commas, any one of them
-n--newestThe most recently started of the matches
-o--oldestThe oldest of the matches
-c--countPrint a count instead of numbers; exit code 1 if none
-d--delimiterSet the delimiter between numbers (newline by default)
-V--versionPrint the version
OptionCopyDescription
-i--ignore-caseSearch case-insensitively
-v--inverseFind processes that do not match
-P--parentOnly children of the given parent number (PPID)
-t--terminalOnly processes attached to the given terminal
-g--pgroupOnly processes in the given process group number
-s--sessionOnly processes in the given session number
-U--uidOnly processes with the same real user ID
-G--groupOnly processes with the same real group ID
-w--lightweightPrint all thread numbers instead of process numbers

🔲 pgrep Command Simulator

The simulator below starts with a list of the six pgdemo and timeout lines plus example processes. Tap the chips to compare the lines each option finds in the list on the left, and check how the result shrinks with [pgrep -l pgdemo] after [pkill pgdemo-b].

pgrep Command Simulatorprocps-ng 3.3
[root@server work]#
Runs only in your browser. The list on the left uses example values, and [Just matched] is added next to the lines pgrep finds. [pkill] only pretends by removing lines from the list.

4️⃣ pgrep vs pidof and pkill

  • ↪️ pidof Finds the Exact Name, pkill Sends a Signal

pidof finds only processes whose program name matches exactly, without regular expressions, and prints the numbers on one line separated by spaces. Searching for pgdemo-a printed both numbers on one line, with 2152, the one started later, first.

pidof pgdemo-a
2152 2143

Unlike pgrep, pidof found nothing for the partial name pgdemo, and the exit code was 1. If you need just one number, add -s. [pidof -s pgdemo-a] printed only 2152.

pidof pgdemo
pidof -s pgdemo-a
2152

To see the start time and parent number (PPID) of the numbers you found, join them with commas using pgrep -d and pass them to -p of the ps command.

pgrep -d, pgdemo
2143,2152,2155
ps -fp $(pgrep -d, -x pgdemo-a)
UID          PID    PPID  C STIME TTY          TIME CMD
root        2143    2141  0 15:59 ?        00:00:00 ./pgdemo-a 300
root        2152    2150  0 15:59 ?        00:00:00 ./pgdemo-a 301

2141 and 2150 in the PPID column are the numbers of the timeout processes that started the two pgdemo-a processes.

pkill finds processes with the same criteria as pgrep, but sends them a signal instead of printing their numbers. Without a signal it sends SIGTERM, and you can change the signal as in [pkill -HUP name].

pkill sends the signal as soon as it finds a match, so check the targets first with [pgrep -a] or [pgrep -af] using the same criteria. With -f, a timeout or a script whose command line contains the same text becomes a target too. If you already know the number, use the kill command to send a signal to that number only.

CommandMatches byOutputTask
pgrepPart of the name (regex), or the whole command line with -fNumbers; name and command line with -l, -aFinds only
pidofWhole program nameNumbers on one lineFinds only
pkillSame criteria as pgrepNoneSignal to the processes found (SIGTERM by default)

🔢 FAQ & Recommended Content

pgrep compares process names only up to the 15 characters kept in /proc/PID/stat. If a name is longer than 15 characters, search with the first 15 characters, or use -f to search the whole command line in /proc/PID/cmdline.

When you filter the ps list with grep, the grep command line also contains the name you are looking for, so it can show up in the results. pgrep never includes itself in the results and prints only numbers, which makes them easy to pass to other commands.

With -v, pgrep inverts the criteria and finds processes that do not match. pkill does not accept the short option -v, to prevent mistakes.

ℹ️ Affiliate Disclosure
This site's content contains affiliate links. When a visitor buys a product or service through one of them, the site receives a commission from the seller. The amount the buyer pays(it goes down during event discounts ↓)does not go up. Posted prices, discounts, and stock reflect the time of writing and may differ, so confirm with the seller before buying. Products are chosen and reviewed by our own standards, and commissions do not affect the order or content of reviews.

Leave a Reply

Your email address will not be published. Required fields are marked *

Prove your humanity: 1   +   4   =