Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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?

share|improve this question
    
Not an answer, but start with ps auxf. –  jftuga Nov 30 '11 at 21:34
2  
@jtfuga This is in fact where I started, but this gives me all processes, which is exactly what I don't want. –  kynan Dec 1 '11 at 9:59

4 Answers 4

pstree ${pid}

where ${pid} is the pid of the parent process.

On gentoo pstree is in the package "psmisc," apparently located at http://psmisc.sourceforge.net/

share|improve this answer
4  
Thanks, should have mentioned that I had looked at pstree, but missed a more verbose output format. However, pstree -p <pid> at least print the pids which is reasonably close. –  kynan Dec 1 '11 at 10:00
    
I have this problem too, I need to gather all child pids recursively but I need only the pids, so I would have to sed all that.. mmm this works :) pstree -pn 4008 |grep -o "([[:digit:]]*)" |grep -o "[[:digit:]]*" –  Aquarius Power Jun 17 at 23:36

Here is my version that runs instantly (because ps executed only once). Works in bash and zsh.

pidtree() (
    [ -n "$ZSH_VERSION"  ] && setopt shwordsplit
    declare -A CHILDS
    while read P PP;do
        CHILDS[$PP]+=" $P"
    done < <(ps -e -o pid= -o ppid=)

    walk() {
        echo $1
        for i in ${CHILDS[$1]};do
            walk $i
        done
    }

    for i in "$@";do
        walk $i
    done
)
share|improve this answer

I have been working to find a solution to the exact same problem. Bascially, ps manpage does document any option allowing to do what we want with a single command. Conclusion: a script is needed.

I came up with a script very similar to yours. I pasted it in my ~/.bashrc so I can use it from any shell.

pidtree() {
  local parent=$1
  local list=
  while [ "$parent" ] ; do     
    if [ -n "$list" ] ; then
      list="$list,$parent"
    else
      list="$parent"
    fi
    parent=$(ps --ppid $parent -o pid h)
  done
  ps -f -p $list f
}
share|improve this answer

I made a similar script based on Philippe's above

pidlist() {
local thispid=$1
local fulllist=
local childlist=
childlist=$(ps --ppid $thispid -o pid h)
for pid in $childlist
do
  fulllist="$(pidlist $pid) $fulllist"
done
echo "$thispid $fulllist"
}

This outputs all the child, grandchild, etc. pids in space-delimited format. This can, in turn, be fed to ps, as in

ps -p $(pidlist pid)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.