6

I'm using ps -eo ppid,pid,cmd to view all process, and how can I format the output to view like below?

Only given PID and its ancestor will print (until init).

23464   current
  |
23211   bash
  |
23210   sshd: xxW
  |
23193   sshd: WWcccv
  |
 728    /usr/sbin/sshd –D
  |
  1     init

I'm writing a script to view ancestral process using PID without using pstree, if possible.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
Asif
  • 321

3 Answers3

4

Maybe something like:

#! /bin/bash -
pid=${1?Please give a pid}
sep=
while
  [ "$pid" -gt 0 ] &&
    read -r ppid name < <(ps -o ppid= -o args= -p "$pid")
do
  printf "$sep%$((3+${#pid}/2))d%$((4-${#pid}/2))s%s\n" "$pid" "" "$name"
  sep=$'  |\n'
  pid=$ppid
done

Which gives:

$ that-script "$$"
13612  /bin/zsh
  |
 4137  SCREEN screen -xRS main
  |
 4136  screen screen -xRS main
  |
 4130  zsh
  |
 4128  xterm
  |
  1    /sbin/init splash

That's a bit sluggish as it runs one ps per process in the ancestry. You can improve it by running ps to retrieve all the information at once and post process it with awk for instance:

#! /bin/sh -
pid=${1?Please give a pid}
ps -Ao pid= -o ppid= -o args= |
  awk -v p="$pid" '
    {
      pid = $1; ppid[pid] = $2
      sub(/([[:space:]]*[[:digit:]]+){2}[[:space:]]*/, "")
      args[pid] = $0
    }
    END {
      while (p) {
        printf "%s%*d%*s%s\n", sep, 3+length(p)/2, p, 4-length(p)/2, "", args[p]
        p = ppid[p]
        sep = "  |\n"
      }
    }'
2

What about using pstree -spa ? It will show both predecessors and ancestors for the given pid, including pid and command lines.

$ pstree -spa 3056
systemd,1
  └─upowerd,3056
      ├─{gdbus},3071
      └─{gmain},3069
-1

Place pid, ppid's into array. Recursive function or loops to walk through the array, printing only the desired pid and ppid entries.

kph0x1
  • 356