Linux 遍历进程树

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5213973/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:08:21  来源:igfitidea点击:

Walking a process tree

linuxshellunixpstree

提问by mkab

I have the following scenario.

我有以下场景。

The user would type the PID of a process, and the script should show the process and it's subprocesses, sub-subprocesses (and so on) of PID, and it should list it in a tree format.

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

I tried using pstree PIDand ps faux PID, but it doesn't work. It seems like it doesn't take PID of processes as arguments.

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

Any ideas please?

请问有什么想法吗?

回答by bmargulies

Your first step is to pipe ps through awk and grep. By using awk, you can isolate either the 'this process PID' field or the 'parent process PID' field.

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

Or, have a stroll through the /proc file system.

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

回答by pmod

This is the bash script using only psand awk. You can use at as a base for generating process tree.

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

ppid=
while true
do 
    forloop=FALSE
    # get all children by pid 
    for i in `ps -ef | awk ' == '$ppid' {print }'`
    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

回答by sdaau

Just wanted to document my steps related to this problem.

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

Say I execute this in a terminal:

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

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

... and leave it waiting at the readinput prompt. Then, I can always find the pid of mytest.shlike:

...并让它在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

... however, I'd like to output a ps axftree limited to some parent of mytest.sh; looking at a full ps axf, we can see a hierarchy:

...但是,我想输出一个ps axf仅限于某些父级的树mytest.sh;查看 full 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
...

Then, say I don't want to 'scan' the gnome-terminal(1489) as parent, but instead I want to start at bash(20238).. So, I'd like to obtain this output:

然后,假设我不想将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

... except, I don't want to copy/paste the child PIDs manually :)

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

I could use pstree:

我可以使用pstree

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

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

... unfortunately, the output is not exactly the same as in ps axf, which I prefer.

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

So, I can use pstreesimply to obtain child PIDs:

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

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

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

and then use those to obtain a ps axftree, based only on the PID of the parent:

然后使用它们来获取一ps axf棵树,仅基于父级的 PID:

$ ps f -p $(pstree -p 20238 | sed 's/(/\n(/g' | grep '(' | sed 's/(\(.*\)).*//' | 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

Well, hope this helps someone,
Cheers!

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