The Limitation of top and ps
When a Linux server starts acting sluggish, the immediate reaction of most administrators is to run top or ps aux to see what is consuming the CPU. These tools dump a massive table of hundreds of running processes onto the screen.
If you are looking for a specific daemon—say, the Nginx web server or a rogue Python script—scanning through 500 lines of output with your eyes is inefficient. Administrators often resort to piping the output through grep: ps aux | grep nginx.
While ps | grep works, it is a clumsy “hack.” It spawns two separate processes, often catches the grep command itself in the output, and requires complex string parsing (using tools like awk) if you actually want to extract the Process ID (PID) to kill it.
Linux has a dedicated, elegant tool designed explicitly to search for processes by their name or attributes: pgrep.
Step 1: The Basic Search
The core function of pgrep is to look up the name of a running program and return its Process ID (PID). The PID is the crucial number you need if you want to inspect a program’s memory or force-kill it.
To find the PID of the SSH daemon, simply type:
pgrep sshd
The terminal will return a clean list of numbers (e.g., 1142, 14552). That is it. No extra text, no usernames, no CPU percentages. Just the pure PID, which makes it perfect for use in bash scripts.
Step 2: Getting More Context (Name and Full Command)
Sometimes just seeing the number 1142 isn’t helpful. You want to confirm exactly what that process is.
Use the -l (list name) flag to output the PID followed by the process name:
pgrep -l python
Output:
4521 python3
8812 python
If you are running multiple instances of the same program with different arguments (e.g., three different Python scripts), the basic name isn’t enough. You need to see the full command-line arguments that were used to launch the process.
Use the -a (full list) flag:
pgrep -a python
Output:
4521 /usr/bin/python3 /opt/scripts/backup.py
8812 python /home/user/test_script.py
This instantly allows you to differentiate between the critical system backup script and a user’s random test script.
Step 3: Exact Matches vs. Partial Matches
By default, pgrep uses partial matching. If you type pgrep sh, it will return the PID for sh, but also bash, sshd, and flush. This can lead to disastrous consequences if you pass those PIDs to a kill command.
To force pgrep to only return processes that perfectly match the string you typed, use the -x (exact) flag.
pgrep -x bash
This will only return instances of the bash shell, ignoring everything else that happens to contain those four letters.
Step 4: Filtering by User
On a multi-user server, you might only care about the processes spawned by a specific user account. A developer might complain that their node.js application is hanging, but you don’t want to accidentally look at the production node.js application running under a different service account.
Use the -u (user) flag followed by the username.
To find all node processes running exclusively under the user account “devteam”:
pgrep -u devteam node
Step 5: Counting Processes
Finally, pgrep is an excellent tool for quick health checks. Instead of listing the PIDs, you can ask it to simply count how many instances of a process are running.
If your web server architecture dictates that there should always be exactly 8 worker processes of Apache (apache2) running, you can verify this instantly using the -c (count) flag:
pgrep -c apache2
If the command returns 8, the system is healthy. If it returns 0, the web server has crashed, and you can program a bash script to automatically trigger a restart or send an alert.