私のスクリプトでは、データセットをinput_aa、input_abなどに分割します。次に、それぞれを同じPythonスクリプトとして実行します:
# Execute program on each split file
for part in input_*; do
python3 $part &
done
wait
私の質問は2つあります:Pythonプロセスが失敗したことを検出するにはどうすればよいですか?また、検出されたときに、生成されたすべての子を強制終了し、失敗してスクリプトを終了するにはどうすればよいですか?
プロセスグループを使用できます。
set -m
(
for part in input_*; do
(python3 "$part" || kill 0) &
done
wait
)
set -m
(およびオプションのPOSIXシェル機能、必須のUnixシェル機能)は、独自のプロセスグループでジョブを実行します。 bash
、yash
、zsh
、mksh
では、それがサブシェルの仕事であり、set -m
が有効になっているため、外側の(...)
およびその中で作成されたすべてのプロセスは、同じプロセスグループに配置されます。
dash
およびその他のash
ベースのシェルの場合、これは最上位のシェルプロセスでのみ機能します。そのため、そのコードはサブシェルに配置されない限り機能します。
これは、AT&T ksh
や古いSysV/BourneShellではまったく機能しません。
kill 0
現在のプロセスグループのすべてのメンバーにSIGTERMシグナルを送信します。
これは一例です。最初にこれで遊んで、必要なものを正確に入手してください。そのままでは壊れません。
#!/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
リダイレクトはログを保存するためにあります。あなたはそれらを望まないかもしれません。