複数のプログラムを実行するbashスクリプトがあります
#!/bin/sh
python program1.py &
python program2.py &
other programs ... &
lastProgram
./myscript.sh
として実行します
Ctl-Cを押してlastProgram
を閉じると、終了し、他のすべてのものはバックグラウンドで実行され続けます。問題は、他のプログラムを終了する必要があることです。
スクリプトから開始されたすべてのプログラムの終了を処理する適切な方法はどれですか。
プロセスIDを収集し、終了時にバックグラウンドプロセスを強制終了します。
#!/bin/bash
killbg() {
for p in "${pids[@]}" ; do
kill "$p";
done
}
trap killbg EXIT
pids=()
background job 1 &
pids+=($!)
background job 2... &
pids+=($!)
foreground job
トラップEXIT
は、理由に関係なく、シェルの終了時に関数を実行します。これをtrap killbg SIGINT
に変更して、^C
でのみ実行できます。
これは、スクリプトがそれらを撮影しようとする前にバックグラウンドプロセスの1つが終了したかどうかをチェックしません。そうした場合、エラーが発生したり、さらに悪いことに、間違ったプロセスを実行したりする可能性があります。
または、ジョブIDで殺します。 jobs
の出力を読んで、まだアクティブなものを見つけましょう。
#!/bin/bash
killjobs() {
for x in $(jobs | awk -F '[][]' '{print $2}' ) ; do
kill %$x
done
}
trap killjobs EXIT
sleep 999 &
sleep 1 &
sleep 999 &
sleep 30
他のプロセスを生成するバックグラウンドプロセス(サブシェル:(sleep 1234 ; echo foo) &
)を実行する場合、これを機能させるには、set -m
(「モニターモード」)を使用してジョブ制御を有効にする必要があります。それ以外の場合は、リードプロセスのみが終了します。
私はPIDの収集について同様の質問を読んでいて、スクリプトの最後にそれらをすべて殺していました-問題は、完了したプロセスのPIDです- リサイクルして新しいプロセスで再利用できますスクリプトが終了する前に、次のことができます新しい(ランダム)プロセスを強制終了します。
Bashのジョブ制御を使用して、トラップと%n jobspecを使用してスクリプトで開始されたプロセスのみを強制終了し、実行可能なジョブの最大数をカウントできます(この例では3つのみ)。
#!/bin/bash
#trap 'kill %1 %2 %3' 0 # 0 or EXIT are equivalent
#trap 'kill %1 %2 %3' EXIT # or use {1..n} as below
trap 'kill %{1..3}' EXIT
sleep 33 &
sleep 33 &
sleep 33 &
echo processes are running, ctrl-c the next sleep
sleep 66
echo this line will never be executed
すでに終了している存在しないjobspecに対する追加の「キル」は、エラーメッセージのみを発生させ、他の新しい/ランダムプロセスを強制終了しません。
ここでは、スクリプトの完全なプロセスグループを強制終了する方法が少し異なります。しかし、スクリプト/シェルのジョブ制御が設定されていない場合、それはcould親からPPIDを継承します...しかし、ジョブ制御なしでは、上記も機能しません。
違いは、新しいプロセスのPGIDになるため、bashのPIDを使用するトラップのこのkillコマンドです。
trap 'kill -- -$$' EXIT
this related Q または ここで、Johannes 'fish' ZiemkeがSIGINTおよびSIGTERMをトラップし、setsid
を使用して "新しいプロセスでプロセスグループ全体をkillします私たち自身を殺すリスクを負わないようにグループ化します。 " )
lastProgram
の実行が完了する前に完了しないバックグラウンドプロセスをすべて強制終了するには、すべてのPIDを保存する必要があります。
python program1.py &
p1pid=$!
python program2.py &
p2pid=$!
other programs ... &
p3pid=$!
lastProgram
kill $p1pid $p2pid $p3pid
スクリプトを終了する前に、すべてのバックグラウンドプロセスの実行が完了するまで待機するだけの場合は、wait
コマンドを使用できます。
python program1.py &
python program2.py &
other programs ... &
lastProgram
wait