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


9

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

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

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

回答:


10

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

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 / Bourneシェルではまったく機能しません。

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


バッシュで。シバンを含めた理由-必要なシェルが明確ではありません。良い答え
ジムマクナマラ2015年

で働く@jimmcnamara、 、bashdashyash、。mksh zsh基本的にすべてのPOSIXシェルですが、AT&T kshです。set -mPOSIXで(過小に)指定されていますが、オプション機能です。
ステファンChazelas

私はSolarisを使用しています。/ bin / shは飛行しません。
ジムマクナマラ2015年

@ jimmcnamara、Solaris 10以前の/ bin / shはBourneシェル(POSIXシェルではない)、11はAT&T kshです。私が言ったように、それはbash、dash、yash、mksh、zshで動作します。
ステファンChazelas

1
@mikeserv、これはプロセスの親を1に変更しますが、プロセスグループから削除しません。kill 0親が何であれ、プロセスグループのすべてのメンバーを殺します。ps -jプロセスグループIDを参照してください。
ステファンChazelas

3

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

#!/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 

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


それは少し際どいです。他のジョブがすべて開始する前にジョブの1つが失敗した場合、開始しkillfileたジョブのすべてのPIDが含まれていない可能性があります。
ステファンChazelas

ユーザ信号として引用符で囲まれていない変数、シグナル番号の代わりに名前を使用する代わりに、USR1 / USR2の使用信号6(例えばABRT LinuxのAMD64)、:のようないくつかの悪い習慣[ $? -ne 0 ]...
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.