How can I get the entire process tree spawned by a given process displayed as a tree and only that tree i.e. no other processes?
The output could e.g. look like
4378 ? Ss 0:10 SCREEN
4897 pts/16 Ss 0:00 \_ -/bin/bash
25667 pts/16 S+ 0:00 | \_ git diff
25669 pts/16 S+ 0:00 | \_ less -FRSX
11118 pts/32 Ss+ 0:00 \_ -/bin/bash
11123 pts/32 S+ 0:00 \_ vi
I couldn't get the desired result purely with parameters to ps
.
The following gives the desired result but seems a bit involved:
#!/bin/bash
pidtree() {
echo -n $1 " "
for _child in $(ps -o pid --no-headers --ppid $1); do
echo -n $_child `pidtree $_child` " "
done
}
ps f `pidtree 4378`
Does anyone have an easier solution?
Best Answer
The
pstree
is a very good solution, but it is a little bit reticent. I useps --forest
instead. But not for aPID
(-p
) because it prints only the specific process, but for the session (-g
). It can print out any informationps
can print in a fancy ASCII art tree defining the-o
option.So my suggestion for this problem:
If the process is not a session leader, then a little bit more trick has to be applied:
This gets the session id (SID) of the current process first and then call ps again with that sid.
If the column headers are not needed add a '=' after each column definition in '-o' options, like:
An example run and the result:
Unfortunately this does not work for
screen
as it sets the sid for each child screen and all grandchild bash.To get all the processes spawned by a process the whole tree needs to be built. I used awk for that. At first it builds a hash array to contain all
PID => ,child,child...
. At the end it calls a recursive function to extract all the child processes of a given process. The result is passed to anotherps
to format the result. The actual PID has to be written as an argument to awk instead of<PID>
:For a SCREEN process (pid=8041) the example output looks like this: