当其中一个子进程退出时退出 bash 脚本

Exit a bash script when one of the subprocesses exits

我运行我的脚本中有几个后台进程

run_gui()
{
    exec ... # the real commands here
}

函数run_ai1(), run_ai2类似。

然后我 运行 函数并完成所需的管道

run_gui &
run_ai1 &
run_ai2 &
while true; do
    while true; do
        read -u $ai1_outfd line || echo "Nothing read"
        if [[ $line ]]; then
            : # processing
        fi
    done
    sleep $turndelay
    while true; do
        read -u $ai2_outfd line || echo "nothing read"
        if [[ $line ]]; then
            : # processing
        fi
    done
    sleep $turndelay
done

如果这三个进程中的任何一个退出,我想检查它们的退出代码并终止其余进程。例如,如果 run_ai2 以退出代码 3 退出,那么我想停止进程 run_ai1run_gui 并以退出代码 1 退出主脚本。不同背景的正确退出代码流程可能不同。

问题是:我怎样才能检测到它?有命令 wait 但我事先不知道哪个脚本会先完成。我可以 运行 wait 作为后台进程 - 但它变得更加笨拙。

你能帮帮我吗?

以下脚本监控测试 child 进程(在示例中为 sleep+false 和 sleep+true)并报告它们的 PID 和退出代码:

#!/bin/bash

set -m

trap myhandler CHLD

myhandler() {
  echo sigchld received
  cat /tmp/foo
}

( sleep 5; false; echo "exit p1=$?" ) > /tmp/foo &
p1=$!
echo "p1=$p1"

( sleep 3; true; echo "exit p2=$?" ) > /tmp/foo &
p2=$!
echo "p2=$p2"

pstree -p $$
wait

结果是:

p1=3197
p2=3198
prueba(3196)─┬─prueba(3197)───sleep(3199)
             ├─prueba(3198)───sleep(3201)
             └─pstree(3200)
sigchld received
sigchld received
exit p2=0
sigchld received
exit p1=1

使用 SIGUSR1 代替 SIGCHLD 可能会很有趣;示例见此处:.

此外,在陷阱处理程序内部,可以验证哪个 child 仍然存在。类似于:

myhandler() {
  if kill -0 $p1; then
    echo "child1 is alive"
  fi 
  if kill -0 $p2; then
    echo "child2 is alive"
  fi 
}

或者当 child 中的一个死亡时杀死他们:

myhandler() {
  if kill -0 $p1 && kill -0 $p2; then
     echo "all childs alive"
  else
    kill -9 $p1 $p2
  fi
}