pgrep Command: Finding a PID by Name, the -f Option, and How pidof and pkill Differ
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
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 pgdemo2143
2152
2155Writing the name up to pgdemo-a left only the two pgdemo-a processes.
pgrep pgdemo-a2143
2152The 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-zzecho $?1Running 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).
pgreppgrep: no matching criteria specified
Try `pgrep --help' for more information.echo $?2By 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 -Vpgrep from procps-ng 4.0.22️⃣ The pgrep -f Option and -l, -a Output
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 pgdemo2143 pgdemo-a
2152 pgdemo-a
2155 pgdemo-bpgrep -a pgdemo2143 ./pgdemo-a 300
2152 ./pgdemo-a 301
2155 ./pgdemo-b 300The 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-a2141
2143
2150
2152Adding -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-a2141 timeout 300 ./pgdemo-a 300
2143 ./pgdemo-a 300
2150 timeout 300 ./pgdemo-a 301
2152 ./pgdemo-a 301When 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-a2141 timeout 300 ./pgdemo-a 300
2143 ./pgdemo-a 300
2150 timeout 300 ./pgdemo-a 301
2152 ./pgdemo-a 301
2160 bash chk.sh pgdemo-aThe 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 3013️⃣ pgrep Matching Options
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 pgdemopgrep -lx pgdemo-a2143 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 pgdemo2143 pgdemo-a
2152 pgdemo-a
2155 pgdemo-bpgrep -u daemon -l pgdemopgrep -u root,daemon -c pgdemo3Giving an account that does not exist produced the [invalid user name] error and exit code 2.
pgrep -u no-such-user9 pgdemopgrep: invalid user name: no-such-user9On 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 sleep3047 sleeppgrep -u user1 -a sleep3047 sleep 60When 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-a2152pgrep -o pgdemo-a2143The 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 pgdemo3pgrep -c pgdemo-zz0Here is a summary of the pgrep options.
| Option | Copy | Description |
|---|---|---|
| -f--full | Search the whole command line instead of the name | |
| -l--list-name | Print the name along with the number | |
| -a--list-full | Print the whole command line along with the number | |
| -x--exact | Find only processes whose whole name matches | |
| -u--euid | Only processes started by the given account; with several separated by commas, any one of them | |
| -n--newest | The most recently started of the matches | |
| -o--oldest | The oldest of the matches | |
| -c--count | Print a count instead of numbers; exit code 1 if none | |
| -d--delimiter | Set the delimiter between numbers (newline by default) | |
| -V--version | Print the version |
| Option | Copy | Description |
|---|---|---|
| -i--ignore-case | Search case-insensitively | |
| -v--inverse | Find processes that do not match | |
| -P--parent | Only children of the given parent number (PPID) | |
| -t--terminal | Only processes attached to the given terminal | |
| -g--pgroup | Only processes in the given process group number | |
| -s--session | Only processes in the given session number | |
| -U--uid | Only processes with the same real user ID | |
| -G--group | Only processes with the same real group ID | |
| -w--lightweight | Print 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].
4️⃣ pgrep vs pidof and pkill
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-a2152 2143Unlike 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 pgdemopidof -s pgdemo-a2152To 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, pgdemo2143,2152,2155ps -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 3012141 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.
| Command | Matches by | Output | Task |
|---|---|---|---|
| pgrep | Part of the name (regex), or the whole command line with -f | Numbers; name and command line with -l, -a | Finds only |
| pidof | Whole program name | Numbers on one line | Finds only |
| pkill | Same criteria as pgrep | None | Signal to the processes found (SIGTERM by default) |
🔢 FAQ & Recommended Content
Real-time check
Linux top Command (Checking CPU and Memory Usage)
A command that shows in real time how much CPU and memory each process uses.
Open files
[Linux] lsof Command: Print Information on Files in Use
A command that shows the files a process has open, along with its PID.
Job control
Linux Background and Foreground: Controlling Processes
How to control jobs by sending a command to the background and bringing it back to the foreground.
ℹ️ 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.