Question

I would like to create a bash alias that gives me the process tree from the current bash session I am using, up to init.

The use case is to know whether I have used bash or vi's :shell command.

I am using MacOS X. I have heard about pstree, but it seems to only show children, not the relationship between init and the current process.

Était-ce utile?

La solution

I am sure with a a bit of google search, you can find how to get and download pstree for the Mac. However, you can do a poor man's version, using ps and ppid.

eg

ps -eo ppid,pid,cmd | awk '{p[$1]=p[$1]","$3}END{ for(i in p) print i, p[i]}'

Autres conseils

This is supported in pstree(1) by using an option to show the tree only for a particular PID and providing the current process's PID ($$ in Bash), The option is named differently between GPL-licensed version by Werner Almesberger distributed with Debian and the BSD version by Fred Hucht distributed with MacOS.

  • On Debian/Ubuntu: pstree -s $$

    init───gnome-terminal───bash───pstree
    

    Summary of -s option:

    -s     Show parent processes of the specified process.
    
  • On MacOS: pstree -p $$

    -+= 00001 root /sbin/launchd
     \-+= 25706philipbranning/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal
       \-+= 25716 root login -pfl philipbranning /bin/bash -c exec -la bash /bin/bash
         \-+= 25722 philipbranning -bash
           \-+= 32456 philipbranning pstree -p 25722
             \--- 32457 root ps -axwwo user,pid,ppid,pgid,command
    

    Summary of -p option:

    -p pid    show only branches containing process <pid>
    

Here's your alias for MacOS:

alias psme='pstree -p $$'

I used Mac OS 10.7 Lion, but I think this will be fairly portable to Bourne-like shells on other Unix-like systems. You may have issues with the command keyword in the argument to ps.

I put the following code in a file named procsup.sh, which defines a shell function to follow the process's parents up to process ID 1. (I often find shell functions easier to work with than aliases.)

procsup()
{
     leaf=$$
     ps -eo pid,ppid,command | awk -v leaf="$leaf" \
        '{parent[$1]=$2;command[$1]=$3;}                                                                                                   
     function print_ancestry(pid)                                                                                                          
     {                                                                                                                                     
         print pid " (" command[pid] ") child of " parent[pid];                                                                            
         if(pid!=1) print_ancestry(parent[pid])                                                                                            
     };                                                                                                                                    
     END{\                                                                                                                                 
         print_ancestry(leaf)                                                                                                              
     }'
}

Then I started a shell and sourced procsup.sh. In real life you would ensure that your new shells would automatically source procsup.sh when started, maybe in your personal .bashrc. First I checked the ancestry from that shell. Then I started vi from that shell. As usual the interaction with vi didn't make it to the transcript until I did :shell. My terminal window looked like this:

Mariel:~/Library/Scripts 1j david$
Mariel:~/Library/Scripts 1j david$
Mariel:~/Library/Scripts 1j david$ . procsup.sh
Mariel:~/Library/Scripts 1j david$ procsup
41926 (-bash) child of 41922
41922 (login) child of 41917
41917 (/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal) child of 19281
19281 (/sbin/launchd) child of 1
1 (/sbin/launchd) child of 0
Mariel:~/Library/Scripts 1j david$
Mariel:~/Library/Scripts 1j david$
Mariel:~/Library/Scripts 1j david$ vi

bash-3.2$ # Have just done :shell.
bash-3.2$ . procsup.sh
bash-3.2$ procsup
42325 (/bin/bash) child of 42324
42324 (vi) child of 41926
41926 (-bash) child of 41922
41922 (login) child of 41917
41917 (/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal) child of 19281
19281 (/sbin/launchd) child of 1
1 (/sbin/launchd) child of 0
bash-3.2$
bash-3.2$

If you use a package manager like MacPorts you can easily install pstree.

I don't have the whole answer that you're looking for, but I've got an idea that might move you in the right direction. The command

declare -A parent

will create an associative array (a hash, if you speak Perl)

You will need some command that will give you name-value pairs for PID and PPID... my guess is that the mac's ps command can be made to do this if you torture it enough. I'm going to use 'ps -eo' as above, but you'll want to fill in the blanks.

Then you can do something like this:

ps -eo pid,ppid | while read pid ppid
do   
   parent[$pid]=$ppid   
   echo "pid: $pid ppid: ${parent[$pid]} grandppid: ${parent[${parent[$pid]}]}"
done

I was having trouble making the values of $parent persist outside of my while loop, otherwise I would have created a second for loop to traverse from $$ back to init. I'll leave that as an exercise to the reader.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top