语境:
用户向我提供他们要运行的自定义脚本。这些脚本可以是任何类型的脚本,例如用于启动多个 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 列表?如能提供任何指点或提示,我将不胜感激
答案1
为了直接回答你的问题,命令
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 脚本中的一个信号也关闭您的子进程,您将需要使用类似这样的方式传播信号(在启动任何进程之前,将其放在顶部的某个地方):
trap 'kill $(jobs -p)' SIGINT SIGTERM EXIT
答案2
谢谢大家的回复..我在 stackoverflow 上找到了解决方案
您可以使用 wait 等待 userscript 启动的所有后台进程完成。由于 wait 仅适用于当前 shell 的子进程,因此您需要获取它们的脚本,而不是将其作为单独的进程运行。
(源用户脚本;等待)
在显式子 shell 中获取脚本应该足够接近地模拟启动新进程。如果没有,您也可以将子 shell 置于后台,这会强制启动新进程,然后等待它完成。
(源用户脚本;等待)&等待
以下是@chepner 原始答案的链接:https://stackoverflow.com/questions/18663196/how-to-get-list-of-all-child-process-spawned-by-a-script/18663969?noredirect=1#18663969