【发布时间】:2011-08-21 14:18:39
【问题描述】:
我想创建一个 bash 别名,它为我提供从我正在使用的当前 bash 会话到 init 的进程树。
用例是知道我是否使用过bash或vi的:shell命令。
我用的是MacOS X,听说过pstree,不过好像只显示children,没有init和当前进程的关系。
【问题讨论】:
我想创建一个 bash 别名,它为我提供从我正在使用的当前 bash 会话到 init 的进程树。
用例是知道我是否使用过bash或vi的:shell命令。
我用的是MacOS X,听说过pstree,不过好像只显示children,没有init和当前进程的关系。
【问题讨论】:
我确信通过一些 google 搜索,您可以找到如何获取和下载 Mac 版 pstree。但是,您可以使用ps 和ppid 做一个穷人的版本。
例如
ps -eo ppid,pid,cmd | awk '{p[$1]=p[$1]","$3}END{ for(i in p) print i, p[i]}'
【讨论】:
ps 很差并且不支持 cmd。我想看看init和当前进程之间的关系。有什么猜测吗?
ps 命令中使用的是comm 而不是cmd。
command 替换cmd 来代替某些版本的BSD 的ps 命令。
pstree(1) 支持这一点,方法是使用选项仅显示特定 PID 的树并提供当前进程的 PID(Bash 中的$$),Werner Almesberger 的 GPL 许可版本之间的选项名称不同与 Debian 一起分发,Fred Hucht 的 BSD 版本与 MacOS 一起分发。
在 Debian/Ubuntu 上:pstree -s $$
init───gnome-terminal───bash───pstree
-s 选项摘要:
-s Show parent processes of the specified process.
在 MacOS 上:pstree -p $$
-+= 00001 root /sbin/launchd
\-+= 25706philipbranning/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal
\-+= 25716 root login -pfl philipbranning /bin/bash -c exec -la bash /bin/bash
\-+= 25722 philipbranning -bash
\-+= 32456 philipbranning pstree -p 25722
\--- 32457 root ps -axwwo user,pid,ppid,pgid,command
-p 选项摘要:
-p pid show only branches containing process <pid>
这是您的 MacOS 别名:
alias psme='pstree -p $$'
【讨论】:
pstree。
pstree $Revision: 2.39 $ by Fred Hucht,这里 -s 选项不起作用,但 -p 选项起作用:pstree -p $$。
-p
我使用的是 Mac OS 10.7 Lion,但我认为这对于其他类 Unix 系统上的类 Bourne shell 来说是相当可移植的。您可能对 ps 参数中的 command 关键字有疑问。
我将以下代码放在名为 procsup.sh 的文件中,该文件定义了一个 shell 函数,以跟踪进程的父进程直到进程 ID 1。(我经常发现 shell 函数比别名更容易使用。)
procsup()
{
leaf=$$
ps -eo pid,ppid,command | awk -v leaf="$leaf" \
'{parent[$1]=$2;command[$1]=$3;}
function print_ancestry(pid)
{
print pid " (" command[pid] ") child of " parent[pid];
if(pid!=1) print_ancestry(parent[pid])
};
END{\
print_ancestry(leaf)
}'
}
然后我启动了一个 shell 并获取了 procsup.sh。在现实生活中,您将确保您的新 shell 在启动时会自动获取 procsup.sh,可能在您的个人 .bashrc 中。首先,我从那个外壳检查了祖先。然后我从那个 shell 开始 vi 。像往常一样,与 vi 的交互直到我做了:shell 才进入成绩单。我的终端窗口如下所示:
Mariel:~/Library/Scripts 1j david$
Mariel:~/Library/Scripts 1j david$
Mariel:~/Library/Scripts 1j david$ . procsup.sh
Mariel:~/Library/Scripts 1j david$ procsup
41926 (-bash) child of 41922
41922 (login) child of 41917
41917 (/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal) child of 19281
19281 (/sbin/launchd) child of 1
1 (/sbin/launchd) child of 0
Mariel:~/Library/Scripts 1j david$
Mariel:~/Library/Scripts 1j david$
Mariel:~/Library/Scripts 1j david$ vi
bash-3.2$ # Have just done :shell.
bash-3.2$ . procsup.sh
bash-3.2$ procsup
42325 (/bin/bash) child of 42324
42324 (vi) child of 41926
41926 (-bash) child of 41922
41922 (login) child of 41917
41917 (/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal) child of 19281
19281 (/sbin/launchd) child of 1
1 (/sbin/launchd) child of 0
bash-3.2$
bash-3.2$
【讨论】:
如果您使用 MacPorts 之类的包管理器,则可以轻松安装 pstree。
【讨论】:
我没有您正在寻找的完整答案,但我有一个想法可能会让您朝着正确的方向前进。命令
declare -A parent
将创建一个关联数组(如果您说 Perl,则为哈希)
您将需要一些命令来为您提供 PID 和 PPID 的名称-值对...我的猜测是,如果您对它进行了足够的折磨,可以使用 mac 的 ps 命令来执行此操作。我将使用上面的“ps -eo”,但您需要填写空白。
然后你可以这样做:
ps -eo pid,ppid | while read pid ppid
do
parent[$pid]=$ppid
echo "pid: $pid ppid: ${parent[$pid]} grandppid: ${parent[${parent[$pid]}]}"
done
我无法让 $parent 的值在我的 while 循环之外持续存在,否则我会创建第二个 for 循环来从 $$ 遍历回到 init。我将把它作为练习留给读者。
【讨论】: