irr*_*aju 11 unix bash shell process bash-scripting
语境:
用户向我提供他们的自定义脚本来运行。这些脚本可以是任何类型的脚本,例如启动多个 GUI 程序、后端服务的脚本。我无法控制脚本的编写方式。这些脚本可以是阻塞类型,即执行等待直到所有子进程(顺序运行的程序)退出
#exaple of blocking script
echo "START"
first_program
second_program
echo "DONE"
Run Code Online (Sandbox Code Playgroud)
或非阻塞类型,即在后台分叉子进程并退出类似的类型
#example of non-blocking script
echo "START"
first_program &
second_program &
echo "DONE"
Run Code Online (Sandbox Code Playgroud)
我想要达到什么目标?
用户提供的脚本可以是上述两种类型中的任何一种,也可以是两者的混合。我的工作是运行脚本并等待它启动的所有进程退出,然后关闭节点。如果它是阻塞类型,情况很简单,即获取脚本执行进程的 PID 并等待 ps -ef|grep -ef PID 没有更多条目。非阻塞脚本给我带来了麻烦
有没有办法获得通过执行脚本产生的所有子进程的 PID 列表?任何指针或提示将不胜感激
要直接回答您的问题,命令
jobs -p
Run Code Online (Sandbox Code Playgroud)
为您提供所有子进程的列表。
但是在您的情况下,使用wait没有任何参数的命令可能会更容易:
first_program &
second_program &
wait
Run Code Online (Sandbox Code Playgroud)
这将等到所有子进程都完成。
另一种选择是使用$!获取最后一个程序的 PID 并可能在变量中累加,如下所示:
pids=""
first_program &
pids="$pids $!"
second_program &
pids="$pids $!"
Run Code Online (Sandbox Code Playgroud)
然后使用等待(这是在您只想等待子进程的子集的情况下):
wait $pids
Run Code Online (Sandbox Code Playgroud)
或者,如果您只想等到任何进程完成,您可以使用
wait -n $pids
Run Code Online (Sandbox Code Playgroud)
如果你想要一个 sigterm 到你的 bash 脚本来关闭你的子进程,你需要用这样的东西传播信号(在开始任何进程之前把它放在顶部的某个地方):
trap 'kill $(jobs -p)' SIGINT SIGTERM EXIT
Run Code Online (Sandbox Code Playgroud)
谢谢大家的回复..我在 stackoverflow 上找到了解决方案
您可以使用 wait 来等待用户脚本启动的所有后台进程完成。由于 wait 仅适用于当前 shell 的子级,因此您需要获取其脚本,而不是将其作为单独的进程运行。
(源用户脚本;等待)
在显式子 shell 中获取脚本应该足够接近地模拟启动新进程。如果没有,您还可以将子 shell 置于后台,这会强制启动新进程,然后等待它完成。
(源用户脚本;等待)&等待
以下是@chepner的原始答案的链接:/sf/ask/1306423751/ ?noredirect =1#18663969