コマンドを並列に実行しますが、親プロセスが終了したら、両方のコマンドを同時に終了しますか?

コマンドを並列に実行しますが、親プロセスが終了したら、両方のコマンドを同時に終了しますか?

シェルが強制終了した場合、両方のコマンドも終了するように、Bashで両方のコマンドを並列に実行する方法はありますか?

簡単な方法は&動作しません。

sh -c 'sleep 6 & sleep 3'

そうすれば、死んでも最初の人はsleep歩き続けるでしょう。sh

答え1

Trapを使用する@lesmanaのソリューションは伝統的なアプローチですが、述べたようにこのkill -9状況を処理することはできません。

メインプロセスを監視し、メインプロセスが終了したときにkillコマンドを実行するようにプロセスを設定する代替方法があります。モニタリングを実行する簡単な方法は、モニターのパイプを設定することです。そして、メインプロセスが終了すると、カーネルはモニターが検出できるパイプを閉じます。

これは例です

#!/bin/bash
# show monitoring main process - Icarus Sparry
# [email protected]

# Handler function. Reads from stdin. If it doesn't read the word clean
# then send SIGINT to the process group.
handler(){
    read
    [ "$REPLY" = "clean" ] || kill -INT -$$
}

# invoke handler as a coprocess. 
coproc handler

# some work in the background, wait for 20 seconds and print a message
{ sleep 20 ; echo bye 20 ; } &

# some work in the foreground
sleep 5 ; echo bye 5

# At this point tell the coprocess it was a clean end, so don't
# terminate the background
echo clean >&"${COPROC[1]}"

bye 5このコマンドを実行すると、5秒後と15秒後に出力されますbye 20。プロセスを終了すると、セカンダリプロセスはバックグラウンドスリープモードを終了します。

フォアグラウンド操作が完了したときにバックグラウンド処理を終了するには、Final を省略し、オプションecho clean >&"${COPROC[1]}"でハンドラから削除し、[ "$REPLY" = "clean" ] ||読み取りと終了はそのままにします。

答え2

trap 'kill 0' EXITメインスクリプトで使用されます。スクリプトが終了すると、すべての子が終了します。スクリプトがどのように終了するかは問題ではありません。とは別にkill -9。これについては後で詳しく説明します。

デモンストレーションするために2つのファイルを作成しました。

$ cat killchildren 
#! /bin/sh
trap 'echo killing all children; kill 0' EXIT # this is the important line
./sleepx 4 &
./sleepx 2
echo killchildren done

$ cat sleepx 
#! /bin/sh
trap 'echo sleep$1 killed' EXIT # just print that it was killed
sleep $1
trap - EXIT # clear trap so not print that it was killed
echo sleep$1 done

ここでは実行され、同じままです。

$ ./killchildren 
sleep2 done
killchildren done
killing all children
sleep4 killed

ここでは正常に終了します。kill(早いタイピングをしないので睡眠時間を増やしました。)

$ ./killchildren &
[1] 13248

$ kill 13248
killing all children
sleep8 killed
sleep10 killed
[1]+  Terminated              ./killchildren

ここでは死んだkill -9

$ ./killchildren &
[1] 13259

$ kill -9 13259
[1]+  Killed                  ./killchildren

$ # ... time passes ...
sleep8 done
sleep10 done

デフォルトスクリプトには終了メッセージがなく、サブスクリプトは終了しません。

あまりテストされていません。 2018年現在、これは少なくともアーチLinuxではshで動作します。


デフォルトのスクリプトが機能しないと機能しませんkill -9。意味論は、kill -9プロセスが何もせずにすぐに終了する必要があるためです。トラップ処理もしません。

つまり、プロセスを殺すことは何でも使用しないでくださいkill -9。これはバグだと思います。その理由の詳細は次のとおりですkill -9

関連情報