1. Overview

A common scenario in Linux system administration is process management. While most processes are easy to stop and manage, there could be some scenarios in which a large number of processes in the same group need to be stopped.

In this tutorial, we’ll take a look at process management using process groups. Also, how to kill all processes that belong to a process group.

2. Process Groups

A process group in Linux, as the name suggests, is a way that Linux groups process together. They are a collection of related processes sharing the same PGID’s (Process Group ID).

A common misconception is that killing the parent process will kill the children’s processes too. Nevertheless,  killing the parent process could allow the child processes to exist on their own. We’ll see how killing a process with the process group id ensures all related processes are stopped.

Each process group has a group leader whose process id is the same as the PGID of all the processes inside the group.

3. Setting Up a List of Grouped Processes

We assume a scenario in which there is a hierarchy of application processes running. Therefore, we’ll create three scripts that will call each other and create a bunch of processes that belong to the same group.

Let’s go ahead and create a shell script named grandparent.sh with the contents below:

#!/bin/bash
bash parent.sh &
bash parent.sh &
for i in {1..100}; do 
sleep 2; 
echo -n "This is the grandparent process $i"; 
done

Similarly, let’s create two more scripts named parent.sh and children.sh:

#!/bin/bash
bash children.sh &
bash children.sh &
for i in {1..100}; do sleep 2; echo -n "This is the parent process $i"; 
done
#!/bin/bash
for i in {1..100}; do 
sleep 2; 
echo -n "This is a test in children process $i"; 
done

Now, let’s  run the topmost script, which will create other processes using the command below:

./grandparent.sh

4. Using the ps Command to Find the Process Group

We’ll be using the ps command to get the list of active processes with the below options:

  • -e: To select all processes
  • -f:  To do a full-format listing, PGID and extra columns are not available in the ps command by default.
  • -j: List process in jobs format.
$ ps -efj
UID          PID    PPID    PGID     SID  C STIME TTY          TIME CMD
root           1       0       1       1  0 11:18 ?        00:00:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 18
root           2       0       0       0  0 11:18 ?        00:00:00 [kthreadd]
root           3       2       0       0  0 11:18 ?        00:00:00 [rcu_gp]
root           4       2       0       0  0 11:18 ?        00:00:00 [rcu_par_gp]
root           6       2       0       0  0 11:18 ?        00:00:00 [kworker/0:0H]
root           8       2       0       0  0 11:18 ?        00:00:00 [mm_percpu_wq]
root           9       2       0       0  0 11:18 ?        00:00:00 [ksoftirqd/0]
root          10       2       0       0  0 11:18 ?        00:00:00 [rcu_sched]

5. Filtering the Process List Output

Depending on the number of processes running in your system, the output will need to be filtered. Let’s use some tools to help us find the Process Groud Id for the process we’re looking to stop.

From our setup in section 3, we should have a group of processes that are sharing the same PGID.

$ ps -efj | egrep "PGID|children|parent"

UID          PID    PPID    PGID     SID  C STIME TTY          TIME CMD
vagrant     6389    5377    6389    5377  0 12:49 pts/0    00:00:00 bash grandparent.sh
vagrant     6390    6389    6389    5377  0 12:49 pts/0    00:00:00 bash parent.sh
vagrant     6391    6389    6389    5377  0 12:49 pts/0    00:00:00 bash parent.sh
vagrant     6393    6390    6389    5377  0 12:49 pts/0    00:00:00 bash children.sh
vagrant     6394    6390    6389    5377  0 12:49 pts/0    00:00:00 bash children.sh
vagrant     6395    6391    6389    5377  0 12:49 pts/0    00:00:00 bash children.sh
vagrant     6397    6391    6389    5377  0 12:49 pts/0    00:00:00 bash children.sh
vagrant     6440    4570    6439    4570  0 12:49 pts/1    00:00:00 grep -E --color=auto PGID|children|parent

As discussed in section 2, the PID of the first process to start all other processes are used as the PGID of all the other processes.

6. Killing a Process Using the PGID

Let’s use the kill command to send a kill signal to the specified process group using the below format:

kill -- -$PGID

The double dash “- -” is for the default SIGTERM signal. As seen in section 5, the PGID of the group of the process that we’re trying to kill is 6389. Knowing this, we can kill this group with the kill command:

kill -- -6389

We can also use any signal we normally use with a process. For example, let’s use SIGKILL -9 to kill the process group:

kill -9 -6389

Additionally, the SIGQUIT signals can be sent to the process groups to replicate a terminal quit signal.

kill -SIGQUIT -6389

7. Conclusion

In this article, we saw how we could use the kill command to terminate processes belonging to the same process group. We can terminate by sending either the SIGTERM or SIGQUIT signal. Using this approach to kill a process helps in scenarios in which a large number of processes are continuously started. a program and all related processes need to be stopped.