2016-05-28 44 views
2

我跑在我的剧本了多个后台进程退出时,子进程的一个退出

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

功能run_ai1(), run_ai2类似于一个bash脚本。

然后我运行的功能,并做必要的管道

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作为后台进程 - 但它变得更加笨拙。

你能帮助我吗?

+1

陷阱SIGCHLD,它允许在执行一些孩子最终声明 –

+0

您可以用[期待](HTTP://期待.sourceforge.net /)?在Expect中,捕获退出子进程比POSIX shell或Bash更优雅。 – nwk

+0

@nwk我期望写一个bash脚本。所以我怀疑这将被允许。 – marmistrz

回答

2

下面的脚本监控测试的子进程(在本例中,睡眠+假和睡眠+真),并报告他们的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 
} 
+0

这将等待两个进程退出。如果第二个是'(yes; echo“exit p2 = $?”)>/tmp/foo&',那么在'false'命令停止后我们的脚本不会停止。 – marmistrz

+0

@marmistrz:当然,现在是时候添加“杀死”命令或任何你需要阻止其他孩子的时间了。 –

+0

好吧,我不应该专注于'wait'。为什么比后台进程有更多的SIGCHLD?为什么在命令结束之前接收到sigchld? – marmistrz