82

When a script is launched from command prompt the shell will spawn a subprocess for that script. I want to show that relationship between terminal level process and its children using ps in a tree style output.
How can I do this?

What I have tried so far

file: script.sh

#!/bin/bash

ps -f -p$1

Then I invoke the script from the command line passing in the process id of the terminal shell:

$ ./script.sh $$

What I want is something like this

  • top level (terminal) shell process
  • ./script.sh
  • process for ps command itself
USER    PID  [..]
ubuntu 123     -bash
ubuntu 1234    \_ bash ./script.sh
ubuntu 12345      \_ ps auxf 

what Im getting is:

  PID TTY      STAT   TIME COMMAND
14492 pts/24   Ss     0:00 -bash
6
  • 3
    Why not use pstree?
    – muru
    Feb 20, 2016 at 9:50
  • @muru I tried pstree and couldn't get it to produce meaningful output, I think pstree $$ just produced bash--pstree not exactly what I was looking for. Feb 20, 2016 at 9:53
  • How is it not what you're looking for? You have replaced the script and ps, so what else do you expect to see except for pstree?
    – muru
    Feb 20, 2016 at 9:55
  • @muru your right its technically what I wanted, but too minimal. i.e. how do you know for sure which processes you are looking at without a PID like ps shows it it table output? Feb 20, 2016 at 10:03
  • 6
    pstree -p $$? Or, if you want more of the command line show, pstree -pa $$. Or, if you want to show all parent processes going up, pstree -psa $$.
    – muru
    Feb 20, 2016 at 10:04

6 Answers 6

103

Try the --forest (or -H) flag

# ps -ef --forest
root     114032   1170  0 Apr05 ?        00:00:00  \_ sshd: root@pts/4
root     114039 114032  0 Apr05 pts/4    00:00:00  |   \_ -bash
root      56225 114039  0 13:47 pts/4    00:00:16  |       \_ top
root     114034   1170  0 Apr05 ?        00:00:00  \_ sshd: root@notty
root     114036 114034  0 Apr05 ?        00:00:00  |   \_ /usr/libexec/openssh/sftp-server
root     103102   1170  0 Apr06 ?        00:00:03  \_ sshd: root@pts/0
root     103155 103102  0 Apr06 pts/0    00:00:00  |   \_ -bash
root     106798 103155  0 Apr06 pts/0    00:00:00  |       \_ su - postgres
postgres 106799 106798  0 Apr06 pts/0    00:00:00  |           \_ -bash
postgres  60959 106799  0 14:39 pts/0    00:00:00  |               \_ ps -aef --forest
postgres  60960 106799  0 14:39 pts/0    00:00:00  |               \_ more
1
  • 10
    The question implied looking for a process tree starting at a specific process, taking $1 argument to a script or using $$ to look at the tree starting at the current shell... Can you update your answer to include information on how to get a forest starting at a specific process?
    – filbranden
    Apr 9, 2018 at 18:42
44

I found it after reading this superuser answer, noting this comment

But not for a PID (-p) because it prints only the specific process, but for the session (-g)

and experimenting

ps f -g<PID>

result

$ ./script.sh $$
  PID TTY      STAT   TIME COMMAND
14492 pts/24   Ss     0:00 -bash
 9906 pts/24   S+     0:00  \_ bash ./script.sh 14492
 9907 pts/24   R+     0:00      \_ ps f -g14492
2
  • 6
    from the man page: OUTPUT MODIFIERS: f ASCII-art process hierarchy (forest)
    – phyatt
    Feb 16, 2017 at 15:33
  • 1
    man page: -g grplist: Select by session OR by effective group name. How does providing a PID result in selection by session?
    – user650654
    Jan 31, 2022 at 23:45
6

Try this:

 $ ps -afx
  PID TTY      STAT   TIME COMMAND
    2 ?        S      0:00 [kthreadd]
    4 ?        I<     0:00  \_ [kworker/0:0H]
    6 ?        I<     0:00  \_ [mm_percpu_wq]
    7 ?        S      0:14  \_ [ksoftirqd/0]
    8 ?        I      0:34  \_ [rcu_sched]
    9 ?        I      0:00  \_ [rcu_bh]
   10 ?        S      0:00  \_ [migration/0]
   11 ?        S      0:00  \_ [watchdog/0]
4

You can use the command ps f -g <PID> and stat the root process for PID:

#> ps f -g 0

PID TTY      STAT   TIME COMMAND
2 ?        S      0:00 [kthreadd]
3 ?        S      0:01  \_ [ksoftirqd/0]
7 ?        S      0:19  \_ [rcu_sched]
1
0

This works for me the best if you only care about your own processes. Have fun.

ps fx | perl -ne "print if /^s*$$/.."'/^\s*$$/'
0

Using pstree -p $$ works for me on macOS Sonoma with Homebrew's pstree, executing it inside a zsh shell running inside the macOS Terminal.app:

>0@16:32:05 L1 :~  
% pstree -p $$
-+= 00001 root /sbin/launchd
 \-+= 03998 roup /System/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal
   \-+= 51052 root login -pf roup
     \-+= 51053 roup -zsh
       \-+= 51139 roup pstree -p 51053
         \--- 51140 root ps -axwwo user,pid,ppid,pgid,command
>0@16:32:11 L1 :~  
% bash
bash-5.2$ zsh

>0@16:32:18 L3 :~  
% pstree -p $$
-+= 00001 root /sbin/launchd
 \-+= 03998 roup /System/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal
   \-+= 51052 root login -pf roup
     \-+= 51053 roup -zsh
       \-+= 51142 roup bash
         \-+= 51143 roup zsh
           \-+= 51180 roup pstree -p 51143
             \--- 51181 root ps -axwwo user,pid,ppid,pgid,command
>0@16:32:27 L3 :~  
% 

Notice the nested shells listed in the second execution of pstree after I created a bash then a zsh nested sub-shells. The zsh shell prompt also shows the shell nested level, which is 3 on the second occurrence.

On Kali Linux, pstree -s $$ works, but lists the processes on a single line:


┌──0─L:1-[~]
└─$ pstree -s $$    
systemd───qterminal───zsh───pstree
                                                                                                                           
┌──0─L:1─[~]
└─$ bash
┌──[~]
└─$ zsh

┌──0─L:3─[~]
└─$ pstree -s $$    
systemd───qterminal───zsh───bash───zsh───pstree
                                                                                                                           
┌──0─L:3─[~]
└─$ 

The -p options prints the PIDs:

┌──1─L:3─[~]
└─$ pstree -s -p $$                                                                                                    1 ⨯
systemd(1)───qterminal(1653597)───zsh(1653600)───bash(1653819)───zsh(1653855)───pstree(1655673)
                                                                                                                           

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .