web-dev-qa-db-ja.com

生成された子プロセスが失敗した場合は、すべてを終了して終了します

私のスクリプトでは、データセットをinput_aa、input_abなどに分割します。次に、それぞれを同じPythonスクリプトとして実行します:

# Execute program on each split file
for part in input_*; do
        python3 $part &
done
wait

私の質問は2つあります:Pythonプロセスが失敗したことを検出するにはどうすればよいですか?また、検出されたときに、生成されたすべての子を強制終了し、失敗してスクリプトを終了するにはどうすればよいですか?

9
Befall

プロセスグループを使用できます。

set -m
(
   for part in input_*; do
     (python3 "$part" || kill 0) &
   done
   wait
)

set -m(およびオプションのPOSIXシェル機能、必須のUnixシェル機能)は、独自のプロセスグループでジョブを実行します。 bashyashzshmkshでは、それがサブシェルの仕事であり、set -mが有効になっているため、外側の(...)およびその中で作成されたすべてのプロセスは、同じプロセスグループに配置されます。

dashおよびその他のashベースのシェルの場合、これは最上位のシェルプロセスでのみ機能します。そのため、そのコードはサブシェルに配置されない限り機能します。

これは、AT&T kshや古いSysV/BourneShellではまったく機能しません。

kill 0現在のプロセスグループのすべてのメンバーにSIGTERMシグナルを送信します。

10

これは一例です。最初にこれで遊んで、必要なものを正確に入手してください。そのままでは壊れません。

#!/bin/bash
# Example of killing off all children

> killfile
> outfile.err
kill_em()
{
   echo 'killing all children ' > 2
   while read pid
   do
      kill -0 $pid && kill -9 $pid  # if still running kill it
   done < killfile
   exit 1
}

export grandparentpid=$$
trap 'kill_em' 6
for i in 2 2 3 4 5 6 7 8 9 10
do
        ( sleep $i && ls oinkle  >> outfile 2>> outfile.err &
          pid=$!
          echo $pid >> killfile
          wait $!
          [ $? -ne 0 ] && kill -6 $grandparentpid
        ) &
done
wait

これは、ls oinkleは失敗します(私のマシンでは)。

スタータースクリプトをいじった後に必要なものが得られたら、次のように変更します。

for i in 2 2 3 4 5 6 7 8 9 10

に:

for part in input_* 

変化する:

sleep $i && ls oinkle 

に:

python3 $part 

リダイレクトはログを保存するためにあります。あなたはそれらを望まないかもしれません。

3
jim mcnamara