93

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? Commented 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. Commented 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? Commented 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? Commented Feb 20, 2016 at 10:03
  • 7
    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 $$. Commented Feb 20, 2016 at 10:04

6 Answers 6

122

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
  • 20
    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? Commented Apr 9, 2018 at 18:42
45

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
  • 7
    from the man page: OUTPUT MODIFIERS: f ASCII-art process hierarchy (forest) Commented Feb 16, 2017 at 15:33
  • 3
    man page: -g grplist: Select by session OR by effective group name. How does providing a PID result in selection by session? Commented Jan 31, 2022 at 23:45
7

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] 
5

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
2

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) 
1

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

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

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.