使用 bash 中的陷阱捕获终止的后台进程的 pid
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9536388/
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
capture pid of terminated background process using trap in bash
提问by jbeard4
I'm writing a bash script that spawns a number of background processes. I'd like to be notified whenever a process terminates; and I would like to know the pid of the terminated process.
我正在编写一个生成许多后台进程的 bash 脚本。我希望在进程终止时收到通知;我想知道终止进程的pid。
I have looked at using wait, such that the pids of each spawned process are captured and stored in an array, and then the array is iterated over, and wait is called on each process. This technique is described in various ways here:
我已经看过 using wait,这样每个产生的进程的 pid 都会被捕获并存储在一个数组中,然后迭代该数组,并在每个进程上调用 wait 。此处以各种方式描述了此技术:
https://stackoverflow.com/a/356154/366856
https://stackoverflow.com/a/356154/366856
The problem with this, if I understand it correctly, is that it can be relatively inefficient if you want to perform some action as soon as an individual process terminates. For example, if you spawn processes A and B, and B finishes before A, then execution must wait for both A and B to finish. I need to perform an action as soon as B finishes.
这样做的问题是,如果我理解正确的话,如果您想在单个进程终止后立即执行某些操作,它的效率可能相对较低。例如,如果您生成进程 A 和 B,并且 B 在 A 之前完成,则执行必须等待 A 和 B 都完成。我需要在 B 完成后立即执行操作。
It seems trap SIGCHLDis the way to perform an action immediately when a child terminates, but the problem is that I cannot find a way to determine the pid of the the source of the SIGCHLD signal, which I also need. The closest thing I've found to a working example of this is the third code example in this post:
这似乎trap SIGCHLD是在孩子终止时立即执行操作的方法,但问题是我找不到确定 SIGCHLD 信号源的 pid 的方法,这也是我需要的。我发现的最接近工作示例的是这篇文章中的第三个代码示例:
http://www.linuxforums.org/forum/programming-scripting/103996-multithreading-bash.html#post510187
http://www.linuxforums.org/forum/programming-scripting/103996-multithreading-bash.html#post510187
I've copy-pasted it here for convenience:
为方便起见,我复制粘贴到这里:
#!/bin/bash
iNext=0
function ChildReturned() {
wait
echo " was returned. Its exits status was: $?"
iNext=$((iNext+1))
StartChild $iNext
}
function StartChild {
./child &
pid=$!
echo "Started: PID= $pid"
trap 'ChildReturned $pid' SIGCHLD
}
set -bm
for (( iNext=0; iNext<=10; iNext++ ));
do
StartChild $iNext
done
wait
I think this example doesn't work, because the author makes the mistake of calling trapmultiple times, each time capturing a different pid variable in trap's argument. Each time trap is called, it overwrites the previous call, and thus an arbitrary pid will be captured. I haven't been able to find a better technique.
我认为这个例子不起作用,因为作者犯了trap多次调用的错误,每次都在trap的参数中捕获不同的 pid 变量。每次调用 trap 时,它都会覆盖之前的调用,因此将捕获任意 pid。我一直找不到更好的技术。
Is there a way to get the pid of a terminated child process using trap in bash?
有没有办法在bash中使用trap获取终止子进程的pid?
Update
更新
I just wanted to point to this resource, which contains the best, most comprehensive overview of solutions to this problem that I have seen thus far:
我只是想指出这个资源,其中包含迄今为止我所看到的针对此问题的最佳、最全面的解决方案概述:
采纳答案by William Pursell
Set the trap once, and in the trap you can call jobs -nto see which children have finished since you last checked. Note that this doesn't tell you which child sent the SIGCHLD; consider the case where two children die before you enter the trap. In that case, you will only enter the trap once, and it is a moot point which child's signal you are actually responding to. Note that -nis a bash extension, and you might prefer to use jobs -l.
设置一次陷阱,在陷阱中您可以调用jobs -n以查看自上次检查以来哪些孩子已完成。请注意,这不会告诉您哪个孩子发送了 SIGCHLD;考虑两个孩子在您进入陷阱之前死亡的情况。在那种情况下,您只会进入陷阱一次,而您实际响应的是哪个孩子的信号,这是一个有争议的问题。请注意,这-n是一个 bash 扩展名,您可能更喜欢使用jobs -l.

