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.