8

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.

Thaddee Tyl
  • 1,126
  • 1
  • 12
  • 17

5 Answers5

7

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 $$'
pneumatics
  • 2,836
  • 1
  • 27
  • 27
  • Thanks! This is exactly what I was looking for! And seems like a better, more direct answer than the accepted one -- given one has access to `pstree` of course. – Wizek Oct 04 '16 at 21:50
  • On OSX I have `pstree $Revision: 2.39 $ by Fred Hucht` and here the `-s` option did not work, but the `-p` option did: `pstree -p $$`. – Alexander Klimetschek Dec 19 '17 at 22:08
  • thanks @AlexanderKlimetschek I've updated the answer to show that `-p` is required for the different version of pstree distributed with MacOS – pneumatics Dec 20 '17 at 02:12
7

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]}'
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
  • Maybe I am wrong, but it seems that pstree, along with you poor man's version, only shows the children of a process. Note that I couldn't properly use your version, since the Mac's `ps` is quite poor and does not support `cmd`. I would like to see the relationship between init and the current process. Any guess? – Thaddee Tyl Aug 21 '11 at 15:06
  • 1
    It seems that OS X is using `comm` instead of `cmd` in the `ps` command. – Thaddee Tyl Aug 21 '11 at 15:22
  • the poor man's version just gets all the parent process and their children together. That's all. – ghostdog74 Aug 21 '11 at 15:25
  • 1
    The poor man's version does not work anymore on OSX Mountain Lion. – Koen. Nov 08 '12 at 22:50
  • Substitute `cmd` with `command` for some versions of BSD's `ps` command. – emallove Oct 25 '16 at 19:24
2

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$
D A Vincent
  • 364
  • 2
  • 21
1

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

Kai Sternad
  • 22,214
  • 7
  • 47
  • 42
1

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.

Barton Chittenden
  • 4,238
  • 2
  • 27
  • 46