In Linux operating systems, some processes have sub processes. The fact that a process has a sub process may actually mean that that process is used for a larger task. Or, the process may need to be divided into sub-processes for easy management. For this and many other reasons, processes with sub-processes appear.
To give a simple example, if you are using a Linux distribution with a GUI (KDE, Gnome, LXDE etc), this desktop environment starts with a process and many sub-processes of that process are born.
List currently running process and sub process
You can list all running processes with the following command in the terminal:
foc@ubuntu22:~$ ps -ef UID PID PPID C STIME TTY TIME CMD root 708 1 0 10:56 ? 00:00:00 /usr/sbin/gdm3 root 724 708 0 10:56 ? 00:00:00 gdm-session-worker [pam/gdm-launch-environ root 735 1 0 10:56 ? 00:00:00 /usr/sbin/cupsd -l kernoops 745 1 0 10:56 ? 00:00:00 /usr/sbin/kerneloops --test kernoops 747 1 0 10:56 ? 00:00:00 /usr/sbin/kerneloops root 751 1 0 10:56 ? 00:00:00 /usr/sbin/cups-browsed gdm 762 1 0 10:56 ? 00:00:00 /lib/systemd/systemd --user gdm 763 762 0 10:56 ? 00:00:00 (sd-pam) rtkit 778 1 0 10:56 ? 00:00:00 /usr/libexec/rtkit-daemon gdm 789 762 0 10:56 ? 00:00:00 /usr/libexec/gvfsd ... gdm 893 816 0 10:56 tty1 00:00:00 /usr/bin/Xwayland :1024 -rootless -noreset gdm 900 1 0 10:56 tty1 00:00:00 /usr/libexec/xdg-permission-store root 906 1 0 10:56 ? 00:00:00 /usr/libexec/packagekitd gdm 915 1 0 10:56 tty1 00:00:00 /usr/bin/gjs /usr/share/gnome-shell/org.gn foc 1303 1 0 10:56 ? 00:00:00 /lib/systemd/systemd --user foc 1304 1303 0 10:56 ? 00:00:00 (sd-pam) gdm 780 775 0 21:58 tty1 00:00:00 /usr/libexec/gnome-session-binary --autostart /usr/share/gdm/greeter/autostart
If you have noticed, PID and PPID values are listed differently. You can see processes with the same PPID (Parent Process ID).
For example, let's see the gdm service and its sub-processes:
foc@ubuntu22:~$ ps -ef | grep 780
gdm 780 775 0 21:58 tty1 00:00:00 /usr/libexec/gnome-session-binary --autostart /usr/share/gdm/greeter/autostart
gdm 799 780 0 21:58 tty1 00:00:01 /usr/bin/gnome-shell
gdm 906 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-sharing
gdm 912 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-wacom
gdm 916 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-color
gdm 923 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-keyboard
gdm 925 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-print-notifications
gdm 927 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-rfkill
gdm 930 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-smartcard
gdm 931 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-datetime
gdm 948 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-media-keys
gdm 950 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-screensaver-proxy
gdm 952 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-sound
gdm 956 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-a11y-settings
gdm 957 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-housekeeping
gdm 962 780 0 21:58 tty1 00:00:00 /usr/libexec/gsd-power
foc 1833 1439 0 22:03 pts/0 00:00:00 grep --color=auto 780
foc@ubuntu22:~$ ps -ef | grep 780 | wc -l
17
17 sub-processes appear. If you are going to use it in a script, the following output may be useful:
foc@ubuntu22:~$ ps -opid --ppid=780 | tail -n +2 | xargs
799 906 912 916 923 925 927 930 931 948 950 952 956 957 962
In this way, you get the ids of the sub-processes of that process.
We will use the pkill command to terminate a process along with its sub-processes.
How to terminate subprocess with pkill?
Pkill terminates processes based on parameters you specify. You can find this command in all Linux distributions.
We will use the -P
parameter. Its usage is as follows:
$ pkill -P $$
$$
is the PID of the current process.-P
parameter: parent PPID,match only child processes of the given parent.
Let's finish pid 780 with the pkill command:
foc@ubuntu22:~$ pkill 780
There were 17 processes above, now let's look at the number of processes again:
foc@ubuntu22:~$ ps -ef | grep 780 | wc -l
16
Although we terminated the main process, the sub processes continued. Now let's kill it with all sub-processes:
foc@ubuntu22:~$ pkill -P 762
Let's show the number of processes again:
foc@ubuntu22:~$ ps -ef | grep 762 | wc -l
1
Only the grep process we're querying appears:
foc@ubuntu22:~$ ps -ef | grep 762
foc 4058 1454 0 21:05 pts/0 00:00:00 grep --color=auto 762
Using pkill in Bash Script
When you need to kill the active process in a script, you can call pkill as follows:
#!/bin/bash echo $$ sleep 15 pkill -P $$
Since the command runs inside the script, it takes the script's process id and kills it.
Using Pkill with Bash Trap Signals
If the script you have prepared is interrupted while it is running, it may be necessary to terminate the process so that other processes do not continue.
For example:
#!/bin/bash echo $$ trap "pkill -P $$" SIGINT sleep 1500
You can kill the process by catching the trap as above.
You can refer to the article "Bash Trap Signals | Capture CTRL+C [Practical Examples]" on Traps.
Summary
In this article, we gave information about the termination of a process with its sub-processes. The pkill command helped us with this. For more information on pkill, run the following command in terminal:
foc@ubuntu22:~$ pkill -h
Usage:
pkill [options] <pattern>
Options:
-<sig>, --signal <sig> signal to send (either number or name)
-q, --queue <value> integer value to be sent with the signal
-e, --echo display what is killed
-c, --count count of matching processes
-f, --full use full process name to match
-g, --pgroup <PGID,...> match listed process group IDs
-G, --group <GID,...> match real group IDs
-i, --ignore-case match case insensitively
-n, --newest select most recently started
-o, --oldest select least recently started
-O, --older <seconds> select where older than seconds
-P, --parent <PPID,...> match only child processes of the given parent
-s, --session <SID,...> match session IDs
...
You can also refer man pkill for more information