I was playing around with some command line tools on an Linux system and tried to get the PID of all child processes. In this article I will present what I have found so far.
To test if the solution I have found is working as expected I have started a terminal emulator with some sub shells. The PID of the terminal emulator is 719.
pgrep
First of all I tried the tool pgrep
. Have a look at the example below.
$ pgrep -P 719
722
1195
1447
3698
4168
4955
5986
9185
9390
9687
11896
Looks good, but let's check if one of the listed processes has also some child processes.
$ pgrep -P 1447
3328
$ pgrep -P 3328
3329
4054
This means I would have to call pgrep for every PID it returns until it returns an empty result. There must be an other solution.
pstree
The next tool I have tried is pstree
. Have a look at the example below.
$ pstree -p 719
qterminal(719)─┬─zsh(722)
├─zsh(1195)
├─zsh(1447)───zsh(3328)─┬─inotifywait(4054)
│ └─ssh-agent(3329)
├─zsh(3698)───man(4127)───less(4142)
├─zsh(4168)───sudo(8912)───su(8913)───bash(8914)───zsh(8921)
├─zsh(4955)───sudo(5207)───su(5208)───bash(5209)
├─zsh(5986)
├─zsh(9185)───ssh(9383)───ssh(9384)
├─zsh(9390)
├─zsh(9687)
├─zsh(11896)
├─{qterminal}(720)
├─{qterminal}(721)
├─{qterminal}(729)
├─{qterminal}(730)
├─{qterminal}(731)
└─{qterminal}(732)
Let's use perl to extract the PIDs.
$ pstree -p 719 | perl -ne 'print "$1\n" while /\((\d+)\)/g'
719
722
1195
1447
3328
4054
3329
3698
4127
4142
4168
8912
8913
8914
8921
4955
5207
5208
5209
5986
9185
9383
9384
9390
9687
11896
720
721
729
730
731
732
Looks like this command shows all the PIDs I was looking for.
Performance
$ time sh -c 'for PID in $(pgrep -P 719); do pgrep -P $PID; done > /dev/null'
sh -c 'for PID in $(pgrep -P 719); do pgrep -P $PID; done > /dev/null' 0,02s user 0,05s system 85% cpu 0,082 total
$ time sh -c 'pstree -p 719 | perl -ne '\''print "$1\n" while /\((\d+)\)/g'\'' > /dev/null'
sh -c 0,02s user 0,01s system 103% cpu 0,029 total
In the tests I have done so far pstree
is faster than the pgrep
solution. Also the pgrep
solution is more complex and the command used does only return the first level of child PIDs. For now I will go with the pstree
version.