3

I know the full command "/bin/child_process" or its pid (3996 in this case) and I'm running ps auxf and then visually identifying its ancestor process /bin/parent_process foobar.

root 3227 0.0 0.0 992 296 ? S<s 10:35 0:00 /bin/parent_process foobar 20058 3987 0.0 0.0 17716 1452 ? S<s 10:35 0:00 \_ /bin/bash 20058 3989 0.0 0.0 19240 1728 ? S< 10:35 0:00 \_ /bin/bash other_args 20058 3996 0.2 1.5 1621804 546104 ? S<l 10:35 0:54 \_ /bin/child_process 

The ancestor process may not always be 3 levels away. Is there a way I can automate this with a command such that I could supply just the pid 3996 or the command /bin/child_process and get out /bin/parent_process foobar? In particular, it will always say /bin/parent_process, but it will have a different argument than foobar every time. The output of ps auxf is very difficult to traverse as a hierarchy to determine a particular ancestor process.

2 Answers 2

2

From the proc manpage (emphasis mine):

/proc/[pid]/stat Status information about the process. This is used by ps(1). It is defined in /usr/src/linux/fs/proc/array.c. pid %d The process ID. The fields, in order, with their proper scanf(3) format speci‐ fiers, are: comm %s The filename of the executable, in parentheses. This is visible whether or not the executable is swapped out. state %c One character from the string "RSDZTW" where R is running, S is sleeping in an interruptible wait, D is waiting in uninterruptible disk sleep, Z is zom‐ bie, T is traced or stopped (on a signal), and W is paging. -----> ppid %d The PID of the parent. <-------- ... 

So what you want can probably be accomplished by parsing /proc/<pid>/stat for the PPID (parent process ID) and then parsing /proc/<ppid>/stat for its PPID and so on until you find a PPID of 1.

The ancestor's command line can be found in /proc/<ancestor_pid>/cmdline.

Note:

Both this method and the pstree method mentioned by icyrock.com assume that your *nix has a proc filesystem which may not always be the case. Since you already have ps, it's safe to assume your system supports procfs.

Edit:

Here's a bash snippet that will implement the above method (assumes pid has been initialized elsewhere):

#Initialize ppid to any value (except 1) to start the loop: ppid=2 while [[ $ppid -ne 1 ]] do ppid=$(cut -d' ' -f4 /proc/${pid}/stat) if [[ $ppid -eq 1 ]] then cat /proc/${pid}/cmdline fi pid=$ppid done 
2

You can use pstree. E.g. I have this currently:

$ pstree -ps 2404 init(1)───lightdm(1911)───lightdm(2293)───sh(2331)───xfce4-session(2395)───{xfce4-session}(2404) 

where pid 2404 is analogous to your /bin/child_process and e.g. pid 1911 is analogous to your /bin/parent_process foobar. You can get the hierarchy easily with this:

$ pstree -ps 2404|sed 's/---/\n/g' init(1) lightdm(1911) lightdm(2293) sh(2331) xfce4-session(2395) {xfce4-session}(2404) 

and then if you want only a specific parent process, you can grep for that:

$ pstree -ps 2404|sed 's/---/\n/g'|grep lightdm lightdm(1911) lightdm(2293) 

In your case, you seem to imply you'll have only one process, so you should have only one entry (e.g. only pid 1911 in my example above). Then if you want to get the command line, you can do something like this:

$ pstree -ps 2404|sed 's/---/\n/g'|grep lightdm|head -n1|sed 's/.*(\([0-9]\+\))/\1/'|xargs ps -o pid,args PID COMMAND 1911 lightdm 

In my case, it did not have any params, but e.g. taking a different pid in the hierarchy does:

$ pstree -ps 2404|sed 's/---/\n/g'|grep sh|head -n1|sed 's/.*(\([0-9]\+\))/\1/'|xargs ps -o pid,args PID COMMAND 2331 /bin/sh /etc/xdg/xfce4/xinitrc -- /etc/X11/xinit/xserverrc 

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.