Episode 020 – pgrep and pkill

This episode the focus will be on two commands that go hand-in-hand: pgrep and pkill. Like the kill command, pkill is used to send a signal to a process usually with the intent to terminate or stop the process. Instead of passing the Process ID (PID) you can pass the process name:

pkill xterm

This example would kill any and all xterm processes with the default SIGTERM signal. Use of this command can be dangerous as it will kill all instances of the listed process unless you specify some limitations. But even then, be careful with this command.

You can specify the signal for pkill to use with the -<signal> or –signal switch. Like kill you can pass either the name or the number:

pkill xterm
pkill -15 xterm
pkill -TERM xterm
pkill -SIGTERM xterm
pkill –signal TERM
pkill –signal 15
pkill –signal SIGTERM

The above examples all do the same thing, terminate xterm with the SIGTERM signal.

The pgrep command allows you to search for processes by name and returns their Process ID (PID). Both pgrep and pkill share many of the same switches and a lot of these switches are best applied to the pgrep command. The pgrep command takes only one required parameter and that is the name of the process you with to get the PID for:

pgrep xterm

What is returned is either a list of the PIDS each echoed to a separate line, or if there is no process found, nothing is returned. With the -l, or –list-name, switch the command will return the PID and the process name:

pgrep -l xterm

May produce an output like this:

1208 xterm
1552 xterm
1680 xterm

If three instances of xterm are running.

The -a or list-full will produce the full command line in addition to the PID:

pgrep -a xterm

May produce the following list:

1208 /usr/bin/xterm
1552 /usr/bin/xterm
1680 /usr/bin/xterm

Note that the -a will not necessarily show the full path to the command unless you actually executed the command using the full path. For instance:

pgrep -l bash
pgrep -a bash

Notice the output in the screenshot below:

pgrep -l and pgrep -a example

pgrep -l and pgrep -a example

Searching bash with the -l only shows “bash”. But using the -a shows instances where bash was called with “/bin/bash” along with just “bash” so you get the full command line that executed the process. This will also include switches but may not include pipes, redirects, or scripts passed to the command.

When passing the process name to the pgrep command the default behavior is to search for processes names that match the pattern. So this:

pgrep -l term

Would return xterm, aterm, eterm, terminal or any other process that had term in the name. Remember that the search is case sensitive so Terminal would not be returned by the pgrep command. If you search:

pgrep -l Term

Because the T has been capitalized, Terminal would be returned but not xterm, aterm, eterm, etc.

The -f, or –full switch tells pgrep to search against the full command line as opposed to just the process name itself. For instance:

pgrep -l bin

May not return anything but:

pgrep -lf bin

Would return all matches that had “bin” in the command line:

 

example of pgrep -lf bin

example of pgrep -lf bin

The -x, or –exact, switch matches explicitly against the process name. So using the above example:

pgrep -xl term

Would return nothing as there is no process called term running. It would not return xterm, aterm, eterm, etc as pgrep was explicitly told to return only the process named “term.” Note the comparison output of the following three commands:

pgrep -l chromium
pgrep -xl chormium
pgrep -fl chromium

example of pgrep -xl term

example of pgrep -xl term

Each produced a different output based on the the switch. The default was to only search for processes containing the name chromium. This included chromium-sandbox. Chromium-sandbox was omitted with the -x switch because we were doing an exact match on the process name for chromium and no more. The final example, using the -f switch, returned a process not returned by the first command: nacl_helper_bootstrap. This process name was returned because the full command line is:

/usr/lib/chromium/nacl_helper_bootstrap

The -f switch matched on “chormium” in the command path whereas the first two examples only matched on the process name itself.

The search can be inverted using the -v, or –inverse, switch which will return all the PIDs but the process listed:

pgrep -vl xterm

This produces a list of all pids that are not the xterm process.

All processes for executed by a specific user can be displayed with the -u, or –euid, switch and passing either the user’s name or user’s id:

pgrep -u dann -l
pgrep -u 1000 -l

This will list out all the processes owned by the user dann. The second example uses the user dann’s userid which is 1000. The -u matches on effective user which means the user id the process is currently running under which may not be the user id the process was started by. The user id the process was started by is the real user id and can be different from effective user id for a given process. To list the processes by real user id use the -U, or –uid, switch:

pgrep -U dann -l
pgrep -U 1000 -l

Like -u, -U can take either user name or user id.

You can also list processes by real group id using the -G, or –group, switch and specifying the group name or group id:

pgrep -G users
pgrep -G 100

The -g, or –pgroup, switch lists all process in a process group:

pgrep -g 772 -l

The next few switches are handy if you want to find out what processes are grouped or attached the other processes. The -s, or –session, switch and pass the session id. This will display all processes in a given session id. You can find session ids using the top or ps commands.

pgrep -s 772 -l

All processes in session 772 will be displayed.

To list all child processes of a given parent process id use the -P, or –parent, switch and provide the Parent PID:

pgrep -P 2523 -l

Note that you must pass the Parent PID, you cannot use the process name.

You can find process groups using the top or ps command.

To list all the processes in a given terminal use the -t, or –terminal, switch and then the terminal name without the /dev/ in front of it:

pgrep -t tty1 -l

This will list all the processes running on terminal tty1 and their PIDs. You can easily find what terminals are being used with the top or ps commands.

If you want to further narrow down the list of processes as opposed there are a few more switches to assist. To list the oldest process in a group use the -o, or –oldest, switch:

pgrep -ol chromium

The output will more than likely list the first chromium process executed. The opposite of this is the -n, or –newest, switch which will display the newest and most likely last process name to be executed in the group:

pgrep -nl chromium

The following screen shot demonstrates this:

example of pgrep -nl chromium

example of pgrep -nl chromium

Notice that the first PID for chromium is 1059 and the last is 15861 and the output of the pgrep command using the -o or -n switches are those PIDs respectively.

There are a few ways to augment the output of pgrep. By default it deliminates each return with a new line. The -d, or –delimeter, switch alters this:

pgrep -d : -l xterm

The output of this command will use : as opposed to the new line between each result:

1015 xterm:1055 xterm:2571 xterm

You can put your delimeter between quotes or double quotes:

pgrep -d” : ” -l xterm
pgrep -d’”:”‘ -l xterm
pgrep -d\”:\” -l xterm

In the first example the delimeter is a “:” with a space before and after the “:”. The second example has the “:” as the delimeter but instead of a space uses double quotes on either side of the “:”. The third example uses the backslash escape instead of encasing the double quotes in single quotes to produce the same delimeter as the second example.

Instead of listing the PIDs you can use pgrep to get a count of the PIDs that would be returned with the -c, or –count, switch:

pgrep -l xterm

produces:

1023
1024
2022
3591

But:

pgrep -c xterm

Produces:

4

It only lists the total of the xterm PIDs which in this case is 4.

The pkill command only uses a subset of the pgrep switches. The following switches can be used by pkill:

  • -f, –full – use full process name to match which may include path
  • -x, –exact – use exact match given to kill processes
  • -g, –pgroup – kill all process in a given process group
  • -G, –group – kill all processs owned by the given group id
  • -u, –euid – kill all processes whose effective user id is given
  • -U, –uid – kill all processes whose real user id is given
  • -s, –session – kill all processes in the session id given
  • -t, –terminal – kill all processes attached to the terminal given
  • -o, –oldest – kill the oldest process of the match given
  • -n, –newest – kill the newest process of the match given

There are a few switches that are relevant more to pkill than pgrep. The first switch is the -e, or –echo, switch that will echo out what pkill has done:

pkill -e xterm

Issuing this would produce output similar to:

xterm killed (pid 1054)

Normally pkill would not return any response if the command was successful. Should you attempt to run this to terminate a process that does not exist you would not receive an error message. Nor would you receive normally receive an error message or an indication that the process did not exist if you ran the pkill without the -e switch.

The pkill command has an option to kill a process by reading PIDs from a file with the -F, or –pidfile. Be aware though it is not a simple as piping a list of PIDs to a file and then having pkill terminate those PIDs listed in the file. That is simply listing PIDs in a file with either a space or newline between them will only result in the first PID receiving the signal from pkill. For instance if your PIDFILE, which for this example is named “killthese”, looks like this:

1025
1050
2351
3555

Issuing this command:

pkill -F killthese

Will only result in process 1025 being sent the signal. The remaining PIDs will not be sent the signal.

The -F switch is primarily used in scripts when you know the PIDFILE to pass to pkill. For instance, many daemons store their PIDFILES in /var/run. The ssh daemon may have a file called /var/run/sshd.pid. The script to start and stop sshd could have a variable set like this:

pidfile=”/var/run/sshd.pid”

The script could kill the sshd process by passing that variable to pkill:

pkill -F /var/run/sshd.pid

The -F switch has a limiter to it with the -L, or –logpidfile, switch. What this limiter does is prevent pkill from sending the signal if the PIDFILE is not locked.  A lock file is a concept to prevent multiple instances of the same process from accessing the same resources. Lock files are typically found in /var/lock. There are programatic and security reasons for implementing lock files. For example, most Linux package managers prevent multiple instances of the package manager from running simultaneously. If you attempt to run a second instance of yum, apt, or pacman to perform an update or install chances are you will receive an error that there is another instance of said package manager that has a lock file in place and that you will not be able to execute the desired process until the other process is completed and the lock released. Attempting to pkill a process that does not have a lock file with the following command:

pkill -LF killfile

Will result in the process not being killed and more an error message like this being generated:

pkill: pidfile not valid

This episode of Linux in the Shell focused on the pgrep and pkill commands. The pgrep command is a very quick and handy way to identify the process id’s for processes that are running on your system. The pkill command, while not as flexible as the kill command in some ways, allows you to easily kill processes by name as opposed to requiring the process id or supplying the full path to the the kill command to be able to kill a process by name.
bibliography

If the video is not clear enough view it off the YouTube website and select size 2 or full screen.  Or download the video in Ogg Theora format:

Thank you very much!

This entry was posted in Uncategorized. Bookmark the permalink.

2 Responses to Episode 020 – pgrep and pkill

  1. Steve Bickle says:

    The -a switch does not exist in the Debian or Fedora version of pgrep on my machines. Very useful command though. Thanks.

    • dannSWashko says:

      You are correct, this must be a fairly new addition. I see it in Arch but not Slackware, Debian, or Centos right now.

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>