如何获取脚本生成的所有子进程的列表


9

内容:

用户向我提供其自定义脚本来运行。这些脚本可以是各种脚本,例如用于启动多个GUI程序,后端服务的脚本。我无法控制脚本的编写方式。这些脚本可以是阻塞类型,即执行等待直到所有子进程(顺序运行的程序)退出

#exaple of blocking script
echo "START"
first_program 
second_program 
echo "DONE"

或非阻塞类型,即在后台派生子进程并退出类似

#example of non-blocking script
echo "START"
first_program &
second_program &
echo "DONE"

我想达到什么目的?

用户提供的脚本可以是以上两种类型中的任何一种,也可以是两者的组合。我的工作是运行脚本,并等待脚本启动的所有进程退出,然后关闭该节点。如果是阻塞类型,则情况很简单,即获取脚本执行过程的PID,然后等到ps -ef | grep -ef PID不再有条目。非阻塞脚本是给我带来麻烦的脚本

有没有一种方法可以获取通过执行脚本生成的所有子进程的PID列表?任何指针或提示将不胜感激


我不认为,除非您可以捕获父级的PID,否则父级脚本结束后是不可能的。如果要启动脚本,则可以将它们包装为类似的东西,这样pid$(foo.sh; echo $!)将为您提供PID,foo.sh因此您可以使用ps --ppid。那行得通吗?
terdon 2013年

2
脚本是否必须在作者用户的UID下运行?如果不是,您是否可以为此目的创建一个虚拟用户?你甚至不需要grep,只是ps –udummy_user。另外,查看过程组。
斯科特

这不是您最初提出的问题的解决方案,而是解决方案:打开一个新的bash会话。您可以列出使用从这个shell产生的所有进程ps不带任何参数(应该是只bashps在开头)。在此处启动脚本。完成后,请等待直到ps | wc -l达到您的期望值。
蒂姆(Tim)

Answers:


8

要直接回答您的问题,命令

jobs -p

为您提供所有子进程的列表。

选择#1

但是在您的情况下,仅使用wait不带任何参数的命令可能会更容易:

first_program &
second_program &
wait

这将等待所有子进程完成。

选择#2

另一种选择是使用$!获取最后一个程序的PID并可能将其累加在一个变量中,如下所示:

pids=""
first_program &
pids="$pids $!"
second_program &
pids="$pids $!"

然后使用wait(如果您只想等待子进程的一个子集):

wait $pids

选择#3

或者,如果您只想等到任何过程完成,则可以使用

wait -n $pids

奖金信息

如果您还希望在bash脚本中使用sigterm来关闭子进程,则需要使用以下方式传播信号(在开始任何进程之前,将其放在顶部):

trap 'kill $(jobs -p)' SIGINT SIGTERM EXIT

1

谢谢大家的答复。我在stackoverflow上找到了解决方案

您可以使用wait等待用户脚本启动的所有后台进程完成。由于wait仅适用于当前shell的子级,因此您需要提供其脚本而不是将其作为单独的进程运行。

(源用户脚本;等待)

在显式子外壳中采购脚本应该足够接近地模拟启动新进程。如果没有,您也可以在子shell后台运行,这将强制启动一个新进程,然后等待其完成。

(源用户脚本;等待)&等待

这是@chepner原始答案的链接:https ://stackoverflow.com/questions/18663196/how-to-get-list-of-all-child-process-spawned-by-a-script/18663969 ? = 1#18663969


3
我也考虑过这一点,但是当用户脚本在后台启动下标然后在后台启动另一个脚本时,此解决方案失败。wait然后,您的命令将等待userscript的子代,但不等待其子代
蒂姆(Tim)

@Tim刚意识到:(
irraju 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.