我可以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
。