使用bash中的陷阱捕获已终止后台进程的pid

时间:2012-03-02 16:00:20

标签: bash unix signals child-process bash-trap

我正在编写一个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?

更新

我只是想指出这个资源,其中包含迄今为止我所看到的解决此问题的最佳,最全面的概述:

http://mywiki.wooledge.org/ProcessManagement#I_want_to_process_a_bunch_of_files_in_parallel.2C_and_when_one_finishes.2C_I_want_to_start_the_next._And_I_want_to_make_sure_there_are_exactly_5_jobs_running_at_a_time

1 个答案:

答案 0 :(得分:3)

设置陷阱一次,在陷阱中,您可以调用jobs -n以查看自上次检查后哪些孩子已完成。请注意,这并不能告诉您哪个孩子发送了SIGCHLD;考虑两个孩子在进入陷阱之前死亡的情况。在这种情况下,您只会进入一次陷阱,这是您实际响应的孩子信号的一个没有实际意义的点。请注意,-n是bash扩展名,您可能更喜欢使用jobs -l