我正在编写一个bash脚本,它会产生许多后台进程。我想在进程终止时收到通知;我想知道终止过程的pid。
我已经看过使用wait
,这样每个衍生进程的pid都被捕获并存储在一个数组中,然后迭代数组,并在每个进程上调用wait。这种技术在这里以各种方式描述:
https://stackoverflow.com/a/356154/366856
如果我理解正确的话,问题在于,如果你想在单个进程终止后立即执行某些操作,那么效率会相对较低。例如,如果您生成进程A和B,并且B在A之前完成,则执行必须等待A和B完成。我需要在B完成后立即执行操作。
似乎trap SIGCHLD
是孩子终止时立即执行操作的方法,但问题是我无法找到确定SIGCHLD信号源的pid的方法,我也需要。我发现的最接近的一个例子就是这篇文章中的第三个代码示例:
http://www.linuxforums.org/forum/programming-scripting/103996-multithreading-bash.html#post510187
为方便起见,我将其复制粘贴在这里:
#!/bin/bash
iNext=0
function ChildReturned() {
wait $1
echo "$1 was returned. Its exits status was: $?"
iNext=$((iNext+1))
StartChild $iNext
}
function StartChild {
./child $1 &
pid=$!
echo "Started: $1 PID= $pid"
trap 'ChildReturned $pid' SIGCHLD
}
set -bm
for (( iNext=0; iNext<=10; iNext++ ));
do
StartChild $iNext
done
wait
我认为这个例子不起作用,因为作者错误地多次调用trap
,每次在trap
的参数中捕获不同的pid变量。每次调用陷阱时,它都会覆盖先前的调用,因此将捕获任意pid。我找不到更好的技术。
有没有办法在bash中使用trap来获取已终止子进程的pid?
更新
我只是想指出这个资源,其中包含迄今为止我所看到的解决此问题的最佳,最全面的概述:
答案 0 :(得分:3)
设置陷阱一次,在陷阱中,您可以调用jobs -n
以查看自上次检查后哪些孩子已完成。请注意,这并不能告诉您哪个孩子发送了SIGCHLD;考虑两个孩子在进入陷阱之前死亡的情况。在这种情况下,您只会进入一次陷阱,这是您实际响应的孩子信号的一个没有实际意义的点。请注意,-n
是bash扩展名,您可能更喜欢使用jobs -l
。