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

yuk*_*ude 19 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
Run Code Online (Sandbox Code Playgroud)

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

但我只想要顶级父PID,在这个例子中它将是800(SSH守护进程).有没有办法轻松做到这一点?

我从这个SO回答中了解到,我可以递归检查/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
Run Code Online (Sandbox Code Playgroud)

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

在我写一个小循环(我甚至不确定你是否可以在bash中使用递归)来做这个之前,是否有一个更简单的方法,我错过了?也许只是文件的另一个参数/proc?一grep,通过这些文件并没有透露任何明显.

编辑:当然,所有Linux进程的顶级进程是/ sbin/init,PID为1.我想要的是前一个父进程的PID:倒数第二个父进程.

Pau*_*ce. 11

Bash绝对可以做递归.

您可以cut通过执行以下操作从stat文件中检索第四个字段而不使用外部实用程序:

stat=($(</proc/$$/stat))    # create an array
ppid=${stat[3]}             # get the fourth field
Run Code Online (Sandbox Code Playgroud)


yuk*_*ude 10

如果没有更好的解决方案,这里有一个简单的(递归)脚本来获取您为其提供的任何进程号的顶级父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
}
Run Code Online (Sandbox Code Playgroud)

只是source这个脚本,并top_level_parent_pid在适当的情况下调用或不调用PID参数.

感谢@Dennis Williamson关于如何紧凑而有效地编写此脚本的许多建议.


Alb*_*ert 5

另一个解决方案(从此处开始):

ps -p $$ -o ppid=
Run Code Online (Sandbox Code Playgroud)