job controlを使用する必要があります。残念ながら、少し複雑です。これらはあなたが実行していることを期待だけでバックグラウンドジョブであれば、あなたはこの1のようなコマンドを実行できます。
jobs \
| perl -ne 'print "$1\n" if m/^\[(\d+)\][+-]? +Running/;' \
| while read -r ; do kill %"$REPLY" ; done
jobs
は、すべてのアクティブなジョブ(実行中のジョブ、プラス最近終了または終了したジョブ)のリストを出力しますこのような形式で:
[1] Running sleep 10 &
[2] Running sleep 10 &
[3] Running sleep 10 &
[4] Running sleep 10 &
[5] Running sleep 10 &
[6] Running sleep 10 &
[7] Running sleep 10 &
[8] Running sleep 10 &
[9]- Running sleep 10 &
[10]+ Running sleep 10 &
(これらは私がfor i in {1..10} ; do sleep 10 & done
を実行して起動ジョブです。)
perl -ne ...
は、実行中のジョブのジョブ番号を抽出するためにPerlを使ってくれています。必要に応じて、明らかに別のツールを使用することができます。 jobs
の出力形式が異なる場合は、このスクリプトを変更する必要があります。上記の出力もCygwin上にあるので、あなたのものと非常によく似ています。
read -r
は、標準入力から「生の」行を読み取り、変数$REPLY
に保存します。 kill %"$REPLY"
は、kill %1
のようなものになり、ジョブ番号1を「キル」(割り込み信号を送信します)になります。と混同しないでください。プロセス番号1が抹消されます)。while read -r ; do kill %"$REPLY" ; done
は、 Perlスクリプトを実行し、それを強制終了します。
ところでブレース展開がパラメータ展開前を取り扱うので、何を持っていることはfor i in "{1" .. "$num}"
に相当していることから、あなたのfor i in {1 .. $num}
は、何を期待しないだろう。 (とにかく、中括弧拡張の中に空白を入れることはできません)残念ながら、私はきれいな代替案を知らない。私はあなたがfor i in $(bash -c "{1..$num}")
のような何かをしなければならないと思う、または算術for
-loopかそれ以外のものに切り替えなければならないと思う。
また、whileループをカッコで囲む必要はありません。 &
は既にジョブをサブシェルで実行します。
すごくきれいだとは言えますが、プロセスグループの管理方法は分かりません。それは、私が産んでいるすべてのバックグラウンドプロセスがスクリプトと同じプロセスグループに入っていることを保証するものですか? – ykaganovich
はい、プロセスグループのデフォルトの動作です。プロセスのグループを明示的に変更してシステムコールを作成するコードを書かない限り、うまくいくでしょう。 –
@RussellDavisこれはとても清潔で、とてもうまく動作します。私はこの作業をするためにマスタースクリプトから生成したすべてのシェルスクリプトにトラップを追加しなければなりませんでした。 – nograpes