【问题标题】:How to display the current process tree of a bash session?如何显示 bash 会话的当前进程树?
【发布时间】:2011-08-21 14:18:39
【问题描述】:

我想创建一个 bash 别名,它为我提供从我正在使用的当前 bash 会话到 init 的进程树。

用例是知道我是否使用过bashvi:shell命令。

我用的是MacOS X,听说过pstree,不过好像只显示children,没有init和当前进程的关系。

【问题讨论】:

    标签: bash process vi ps


    【解决方案1】:

    我确信通过一些 google 搜索,您可以找到如何获取和下载 Mac 版 pstree。但是,您可以使用psppid 做一个穷人的版本。

    例如

    ps -eo ppid,pid,cmd | awk '{p[$1]=p[$1]","$3}END{ for(i in p) print i, p[i]}'
    

    【讨论】:

    • 也许我错了,但似乎 pstree 以及你这个可怜的人的版本只显示了一个进程的子进程。请注意,我无法正确使用您的版本,因为 Mac 的 ps 很差并且不支持 cmd。我想看看init和当前进程之间的关系。有什么猜测吗?
    • 似乎 OS X 在ps 命令中使用的是comm 而不是cmd
    • 穷人的版本只是把所有的父进程和他们的孩子放在一起。就是这样。
    • 穷人的版本在 OSX Mountain Lion 上不再工作了。
    • command 替换cmd 来代替某些版本的BSD 的ps 命令。
    【解决方案2】:

    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
    • 在 OSX 上我有 pstree $Revision: 2.39 $ by Fred Hucht,这里 -s 选项不起作用,但 -p 选项起作用:pstree -p $$
    • 感谢@AlexanderKlimetschek 我已经更新了答案以表明与 MacOS 一起分发的不同版本的 pstree 需要-p
    【解决方案3】:

    我使用的是 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$
    

    【讨论】:

      【解决方案4】:

      如果您使用 MacPorts 之类的包管理器,则可以轻松安装 pstree。

      【讨论】:

        【解决方案5】:

        我没有您正在寻找的完整答案,但我有一个想法可能会让您朝着正确的方向前进。命令

        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。我将把它作为练习留给读者。

        【讨论】:

          猜你喜欢
          • 2017-06-06
          • 1970-01-01
          • 2017-03-19
          • 2015-07-24
          • 1970-01-01
          • 2013-06-06
          • 2010-11-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多