如何自动执行从给定 pid 或命令查找特定祖先进程的手动任务?

如何自动执行从给定 pid 或命令查找特定祖先进程的手动任务?

我知道完整的命令“/bin/child_process”或其 pid(在本例中为 3996),并且我正在运行ps auxf,然后直观地识别其祖先进程/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

祖先进程可能并不总是相距 3 个级别。有没有一种方法可以使用命令自动执行此操作,以便我可以仅提供 pid3996或命令/bin/child_process并退出/bin/parent_process foobar?特别是,它总是会说,但每次/bin/parent_process都会有不同的参数。foobar的输出ps auxf很难作为层次结构进行遍历以确定特定的祖先进程。

答案1

proc联机帮助页(强调我的):

/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. <--------
          ...

因此,您想要的可能可以通过解析/proc/<pid>/statPPID(父进程 ID)然后解析/proc/<ppid>/stat来完成它是PPID 依此类推,直到找到 PPID 为 1 为止。

祖先的命令行可以在 中找到/proc/<ancestor_pid>/cmdline

笔记:

此方法和pstreeicyrock.com 提到的方法都假设您的 *nix 有一个proc文件系统,但情况可能并非总是如此。既然您已经拥有了ps,就可以放心地假设您的系统支持procfs

编辑:

这是一个将实现上述方法的 bash 片段(假设pid已在其他地方初始化):

#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

您可以使用pstree。例如我目前有这个:

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

其中 pid 2404 类似于您的/bin/child_process,例如 pid 1911 类似于您的/bin/parent_process foobar.您可以通过以下方式轻松获得层次结构:

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

然后如果你只想要一个特定的父进程,你可以 grep :

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

就您而言,您似乎暗示您只有一个进程,因此您应该只有一个条目(例如,在上面的示例中只有 pid 1911)。然后如果你想获取命令行,你可以这样做:

$ 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

就我而言,它没有任何参数,但例如在层次结构中采用不同的 pid 会:

$ 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

相关内容