13

我有以下情况。

用户输入进程的 PID,脚本应该显示进程及其子进程、PID 的子子进程(等等),并且应该以树格式列出它。

我尝试使用pstree PIDand ps faux PID,但它不起作用。似乎它没有将进程的 PID 作为参数。

请问有什么想法吗?

4

3 回答 3

26

只是想记录我与此问题相关的步骤。

假设我在终端中执行此操作:

~$ echo "read -p 'Press Enter'" > mytest.sh
~$ chmod +x mytest.sh
~$ bash -c bash
~$ bash -c ./mytest.sh

...并让它在read输入提示符处等待。然后,我总能找到mytest.sh类似的pid:

$ ps axf | grep mytest
20473 pts/2    S+     0:00              |   |   \_ grep --color=tty mytest
20308 pts/5    S+     0:00              |   |       \_ bash -c ./mytest.sh

...但是,我想输出一个ps axf仅限于某些父级的树mytest.sh;看一个完整的ps axf,我们可以看到一个层次结构:

$ ps axf

 1489 ?        Sl     1:39              \_ gnome-terminal --sm-client-id 106ab86
 1511 ?        S      0:00              |   \_ gnome-pty-helper
...
20238 pts/5    Ss     0:00              |   \_ bash
20274 pts/5    S      0:00              |   |   \_ bash
20308 pts/5    S+     0:00              |   |       \_ bash -c ./mytest.sh
...

然后,假设我不想“扫描” gnome-terminal(1489)作为父级,而是我想从bash(20238)开始。所以,我想获得这个输出:

$ ps f -p 20238 20274 20308
  PID TTY      STAT   TIME COMMAND
20238 pts/5    Ss     0:00 bash
20274 pts/5    S      0:00  \_ bash
20308 pts/5    S+     0:00      \_ bash -c ./mytest.sh

...除了,我不想手动复制/粘贴子 PID :)

我可以使用pstree

$ pstree -a -p 20238
bash,20238
  └─bash,20274
      └─bash,20308 -c ./mytest.sh

$ pstree -p 20238
bash(20238)───bash(20274)───bash(20308)

ps axf...不幸的是,输出与我更喜欢的 in 不完全相同。

因此,我可以pstree简单地使用来获取子 PID:

$ pstree -p 20238 | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/'
20238
20274
20308

$ pstree -p 20238 | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/' | tr "\n" ,
20238,20274,20308,

然后使用这些来获得一ps axf棵树,仅基于父级的 PID:

$ ps f -p $(pstree -p 20238 | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*/\1/' | tr "\n" " ")
  PID TTY      STAT   TIME COMMAND
20238 pts/5    Ss     0:00 bash
20274 pts/5    S      0:00  \_ bash
20308 pts/5    S+     0:00      \_ bash -c ./mytest.sh

好吧,希望这对某人有所帮助,
干杯!

于 2011-03-15T11:58:47.320 回答
2

这是仅使用psawk的 bash 脚本。您可以使用 at 作为生成流程树的基础。

ppid=$1
while true
do 
    forloop=FALSE
    # get all children by pid 
    for i in `ps -ef | awk '$3 == '$ppid' {print $2}'`
    do 
       # Here you have one of of the elements of tree 
       #   parent -> child
       echo $ppid - $i 
       forloop=TRUE
    done
    ppid=$i

    if [ "$forloop" = "FALSE" ]; then
       exit
    fi
 done
于 2011-03-06T23:17:02.183 回答
1

您的第一步是通过 awk 和 grep 对 ps 进行管道传输。通过使用 awk,您可以隔离“​​此进程 PID”字段或“父进程 PID”字段。

或者,浏览一下 /proc 文件系统。

于 2011-03-06T22:44:29.423 回答