2016-05-28 68 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