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

时间:2016-05-28 08:31:31

标签: bash background-process pid

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

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.不同背景的正确exitcodes流程可能有所不同。

问题是:我该如何检测它?有wait命令,但我事先并不知道哪个脚本会先完成。我可以运行wait作为后台流程 - 但它变得更加笨拙。

你能帮我吗?

1 个答案:

答案 0 :(得分:2)

以下脚本监视测试子进程(在示例中,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可能会很有趣;请看这里的示例:https://stackoverflow.com/a/12751700/4886927

此外,在陷阱处理程序内部,可以验证哪个孩子还活着。类似的东西:

myhandler() {
  if kill -0 $p1; then
    echo "child1 is alive"
  fi 
  if kill -0 $p2; then
    echo "child2 is alive"
  fi 
}
当其中一个孩子去世时,

或杀死两个孩子:

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