bash - 如何使用 bash 找到给定进程的顶级父 PID?

标签 bash process

假设我运行 ps axf,我可以看到我的命令的进程树如下所示:

  800 ?        Ss     0:00 /usr/sbin/sshd
10186 ?        Ss     0:00  \_ sshd: yukondude [priv]
10251 ?        S      0:00      \_ sshd: yukondude@pts/0
10252 pts/0    Ss     0:00          \_ -bash
10778 pts/0    S      0:00              \_ su -
10785 pts/0    S      0:00                  \_ -su
11945 pts/0    R+     0:00                      \_ ps axf

我知道我可以检查 $$ 获取当前 shell 的 PID (10785) 或检查 $PPID 获取父 PID (10778)。

但我只想要顶级父 PID,在本例中为 800(SSH 守护程序)。有什么方法可以轻松做到这一点?

我从this SO answer中学到了我可以递归检查 /proc/PID/stat 文件中的第 4 个条目以找到每个进程的父 PID:

# cut -f4 -d' ' /proc/10785/stat
10778
# cut -f4 -d' ' /proc/10778/stat
10252
# cut -f4 -d' ' /proc/10252/stat
10251
# cut -f4 -d' ' /proc/10251/stat
10186
# cut -f4 -d' ' /proc/10186/stat
800
# cut -f4 -d' ' /proc/800/stat
1

(顶级父 PID 将是我到达 init 的 PID 之前的那个,即 1。)

在我编写一个小循环(我什至不确定您是否可以在 bash 中使用递归)来执行此操作之前,是否有我缺少的更直接的方法?也许只是 /proc 下文件的另一个参数?通过这些文件的 grep 没有揭示任何明显的东西。

编辑:当然,所有Linux进程的顶层进程都是/sbin/init,PID为1。我要的是之前父进程的PID:倒数第二个 parent 。

最佳答案

如果没有更好的解决方案,这里有一个简单的(递归)脚本,用于获取您提供的任何进程号的顶级父 PID(如果您省略 PID 参数,则为当前 shell):

#!/bin/bash
# Look up the top-level parent Process ID (PID) of the given PID, or the current
# process if unspecified.

function top_level_parent_pid {
    # Look up the parent of the given PID.
    pid=${1:-$$}
    stat=($(</proc/${pid}/stat))
    ppid=${stat[3]}

    # /sbin/init always has a PID of 1, so if you reach that, the current PID is
    # the top-level parent. Otherwise, keep looking.
    if [[ ${ppid} -eq 1 ]] ; then
        echo ${pid}
    else
        top_level_parent_pid ${ppid}
    fi
}

只需获取此脚本并调用top_level_parent_pid,根据需要使用或不使用 PID 参数。

感谢@Dennis Williamson 就如何简洁高效地编写此脚本提出了许多建议。

关于bash - 如何使用 bash 找到给定进程的顶级父 PID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3586888/

相关文章:

bash - 使用长选项正确使用 bash getopts

linux bash - 以自定义格式解析日期

c++ - 从进程中删除 PROCESS_TERMINATE 访问权限,由 CreateProcessWithLogonW 创建

用于创建图像文件的 Java ProcessBuilder 输出

c# - 从 C# 关闭最小化/图标化进程

mysql - 通过远程控制台连接azure的 "MySQL in app"数据库

linux - 使用shell脚本删除前10个最大的常规文件

linux - 在 bash 脚本中运行 Matlab; matlab : not found

java - 如何查看进程的进度

python - 如何使用 python 显示当前用户的进程列表?