如何找到一个进程的祖先链?

如何找到一个进程的祖先链?

我可以ps -o "pid,ppid,args" -p my_pid找到的父母my_pid

我可以继续ps -o "pid,ppid,args" -p previously_found_ppid循环直到到达ppid=1

但是,我敢打赌,肯定有一个单一调用解决方案,它会从父节点开始my_pid并列出其所有祖先。与之相反的方案pstree是从父节点开始并列出其所有后代。您能说出这样的 Unix/Linux 命令是否随时可用吗?

答案1

它看起来pstree可以做你想做的事,-s 显示指定进程的父进程选项

$ pstree -s 5698 
init───mdm───mdm───init───at-spi-bus-laun───dbus-daemon

或者使用选项获取更多信息(参数)和更漂亮的-a选项

mint@mint ~ $ pstree -s -a 5698 
init
  └─mdm
      └─mdm
          └─init --user
              └─at-spi-bus-laun
                  └─dbus-daemon --config-file=/etc/at-spi2/accessibility.conf ...

或者几个选项一起

$ pstree -s -p -a -G -l 5698 
init,1
  └─mdm,1994
      └─mdm,5358
          └─init,5379 --user
              └─at-spi-bus-laun,5691
                  └─dbus-daemon,5698 --config-file=/etc/at-spi2/accessibility.conf --nofork --print-address 3

答案2

pstree可用于打印进程的所有祖先。但最新的 Linux 发行版使用systemd来代替init

例如:pstree -p -s 6206 将给出以下输出

systemd(1)───lightdm(1066)───lightdm(1191)───upstart(1360)───gnome-terminal-(5222)───bash(5229)───cpu-print(6206)

systemd 可以指守护进程周围的所有软件包、实用程序和库。它旨在克服 init 的缺点 [1]。

参考文献[1]:https://www.tecmint.com/systemd-replaces-init-in-linux/

答案3

再次使用Linux版本pstree(macOS 版本有不兼容的选项),这里有一个方便的 Bash 函数,可以根据给定的 PID 打印出进程的祖先链(如果没有给出,则默认为当前 shell 进程$$):

# show the process chain
# pschain [-n] [-r] [PID]
#  -n: show process names
#  -r: show root of chain (PID 1)
# PID: default is current shell
pschain() {
  local name=0 root=0 pid
  while [[ "$1" == -* ]]; do
    [[ "$1" == *n* ]] && name=1
    [[ "$1" == *r* ]] && root=1
    shift
  done

  pid=${1:-$$}
  pstree -pasTA $pid | \
    awk -v NAME=$name -v ROOT=$root -v PID=$pid '{
      while (match($0, /((\s+\|)*\s*[`|]-)?([^,]+),([0-9]+).*/, a)) {
        pid=a[4]; name=a[3]
        if (ROOT == 0) { ++ROOT; next }
        if (NAME == 1) {
          printf "%-6u %s\n", pid, name
        } else { print pid }
        if (pid == PID) exit
        $0 = substr($0, RSTART+RLENGTH)
      }
    }'
}

$ pschain -nr
1      systemd
104805 tmux: server
104808 bash
105236 gdu-go
105442 bash

由于链的根(PID 1)几乎总是systemd/ init(除非它是容器进程),所以默认情况下它是隐藏的,但可以使用选项显示-r

相关内容