1. Overview
We might need to get the child processes of a process in Linux as a part of process administration.
In this tutorial, we’ll discuss several ways of achieving this goal. In our discussion, we will be referring to process identifiers (PIDs), thread identifiers (TIDs), and the /proc file system.
2. Setting up the Test Scenario
We’ll set up a scenario as an example for our tutorial. In this scenario, there will be both parent and child processes.
Let’s start with creating a shell script named child.sh:
#!/bin/bash
sleep infinity
Our goal of this shell script is to just have a forever-running process, as the process spawned by running this script will wait in the sleep infinity command. In addition to this script, we will have another shell script named parent.sh:
#!/bin/bash
./child.sh &
sleep infinity
This shell script first starts the script, child.sh, as a background process. Then, it waits forever in its own sleep infinity command.
Now, let’s run the script, parent.sh:
$ parent.sh &
[1] 6245
The process spawned by running the script, parent.sh, has a process ID (PID) of 6245. We’ll try to find the child processes of this process in the rest of the tutorial.
3. Using the pgrep Command
A simple way to find the child’s processes is to use the pgrep command. The pgrep command lists the currently running processes according to the search criteria supplied to it. These search criteria are supplied with several command options, and the -P option is one of them. The -P option expects to take a PID. This PID is the PID of the parent process whose child processes we want to find. Let’s check the child processes of the process with PID 6245 using the pgrep command:
$ pgrep -P 6245
6246
6247
As we can see, we got two PIDs for the process with PID 6245. We can list the process names with the -l option:
$ pgrep -lP 6245
6246 child.sh
6247 sleep
As is apparent from the outputs of the commands we executed, the pgrep command just lists the direct child processes of a parent process. It doesn’t list the children of child processes, i.e., indirect child processes. In our example, there’s also a direct child process of the process with PID 6246 – the process spawned by executing the sleep infinity command in the script child.sh. But, we don’t see it in the output as it isn’t a direct child process of the process with PID 6245.
4. Using the pstree Command
The pstree command can also be used for displaying the child processes of a parent process. It takes a PID with its -p option. The supplied PID to the -p option is used as the PID of the parent process. It displays the child processes of the parent process as a tree. Let’s check the child processes of the process with PID 6245 using the pstree command:
$ pstree -p 6245
parent.sh(6245)---child.sh(6246)---sleep(6248)
|-sleep(6247)
The pstree command shows not only the direct child processes but also the indirect child processes as a tree. The sleep processes with PIDs 6247 and 6248 are the processes created by running the sleep infinity statements in the scripts parent.sh and child.sh, respectively.
We might also use the –parent option instead of the -p option. They are exactly the same.
5. Using the ps Command
The ps command lists the currently running processes and their PIDs. We can pass the –ppid option to the ps command for finding the child processes. This option expects to take a PID, just like the pgrep command. This PID is the PID of the parent process whose child processes we want to find. So, let’s find the child processes of the process with PID 6245 using the ps command:
$ ps --ppid 6245
PID TTY TIME CMD
6246 pts/1 00:00:00 child.sh
6247 pts/1 00:00:00 sleep
We can format the output of the ps command and print only the PIDs, parent PIDs, and commands:
$ ps --ppid 6245 -o pid,ppid,cmd
PID PPID CMD
6246 6245 /bin/bash ./child.sh
6247 6245 sleep infinity
The output of the ps command is like the output of the pgrep command – it doesn’t list the indirect child processes but only lists the direct child processes. In our example, although there’s a child process of process with PID 6246, we don’t see it in the output. It is the process that the script child.sh spawned by executing the sleep infinity command.
6. Using the /proc File System
We can also find the child processes of a parent process using the /proc directory. In fact, this isn’t a directory but a virtual file system mounted at /proc automatically by the system. It contains information about the kernel, system, and processes.
We can find the PIDs of the child processes of a parent process in the children files located in the /proc/[pid]/task/[tid] directories. Let’s explain the directory structure a little bit.
Let’s start with the [pid] part of the path. The /proc directory contains one subdirectory for each running process. The name of each subdirectory is the PID of the corresponding process.
There is one [tid] subdirectory in the /proc/[pid]/task directory for each thread of the process. Hence, we called the name of this subdirectory as [tid] (thread id). The subdirectory corresponding to the main thread is the same as the PID of the process.
Keeping in mind the explanations so far, let’s investigate the directory structure in our example:
$ ls /proc/6245/task
6245
$ cat /proc/6245/task/6245/children
6246 6247
We have the directory /proc/6245 for the process obtained by running the parent.sh script. There is only one directory, /proc/6245/task/6245, since our process is not multi-threaded. The PIDs of the child processes of the parent process with PID 6245 is in the /proc/6245/task/6245/children file, namely 6246 and 6247.
We can continue inspection in the same manner:
$ ls /proc/6246/task
6246
$ cat /proc/6246/task/6246/children
6248
$ ls /proc/6248/task
6248
$ cat /proc/6248/task/6248/children
$ ls /proc/6247/task
6247
$ cat /proc/6247/task/6247/children
As we see from the output of the execution of the above commands, the process with PID 6246 has only one child. Its PID is 6248. The processes with PIDs 6247 and 6248 don’t have any child processes. The children files corresponding to these processes are empty. So, the child processes we got are the same as the ones obtained by running the pstree command.
We can automate the above recursive process using a shell script, namely find_children.sh:
#!/bin/bash
# root_pid: The PID passed to the script
# That is the PID of the process whose child processes we want to find
root_pid=$1
# all_children: Array that shall store the child processes
declare -A all_children
all_children=()
# Recursive function to find the child processes
iterate_children()
{
local pid=$1
local tids=$(ls /proc/$pid/task)
# Iterate over all [tid]s in /proc/$pid/task directory
for tid in $tids
do
if [ -e /proc/$pid/task/$tid/children ]
then
# Get the child processes in /proc/$pid/task/$tid/children
local children=$(cat /proc/$pid/task/$tid/children)
# Iterate over all child processes
for p in $children
do
# Add the found child process to all_children array
all_children[${#all_children[@]}]=$p
# Find the child processes of process $p
iterate_children $p
done
fi
done
}
iterate_children $root_pid
echo "All child processes of process with PID $root_pid:"
echo ${all_children[*]}
When we run this script, we get the same result:
$ ./find_children 6245
All child processes of process with PID 6245:
6246 6248 6247
7. Conclusion
In this tutorial, we discussed several ways of getting the child processes of a process. The pgrep and ps commands are useful in finding the direct child processes of a parent process. The pstree command lists all of the direct and indirect child processes in a tree structure. We can also find the child processes of a parent process in the /proc file system recursively. We also supplied a shell script for automatically finding all of the child processes using the /proc file system.