シェルスクリプトで非同期whileループを停止する

シェルスクリプトで非同期whileループを停止する

特定の条件が満たされるまでプロセスを再開する非同期whileループがあります。これは次のとおりです。

(while [ "$check_condition" -eq 1 ]; do
    ./async_command
done) &

... # do some stuff

check_condition=0
pkill -9 async_command

ご覧のとおり、check_condition0に変更してまだ実行中の非同期プロセスを終了しました。問題は、whileループが実行され続け、プロセスが再起動されることです。

私はループがcheck_condition開始後にのみ値を登録し、どんな変更も気付かないと思います。

この問題をどのように解決できますか?

答え1

kill $!バックグラウンドで実行されている最後のプロセスを終了する必要があります。バラよりBashスクリプトで「$!」とはどういう意味ですか?

バックグラウンドで別のコマンドを実行している場合は、そのPIDを変数に保存し、$!後でそのIDを使用して必要に応じてプロセスを終了できます。

( while ... done ) & pid=$!

それから

kill $pid

または、jobs実行中のバックグラウンドプロセスを確認し、そのIDを使用して終了します。

kill %Id

また、見ることができますバックグラウンドプロセスを終了するには?

答え2

coproc名前付きループをシミュレートするために使用されます。

名前付きループに最も近いものはbash次のとおりですcoproc

coproc loop1 { while ((1)) ; do echo a >> aout ; sleep 1 ; done ;} 
echo PID of loop1 $loop1_PID
coproc loop2 { while ((1)) ; do echo b >> bout ; sleep 1 ; done ;} 
echo PID of loop2 $loop2_PID
coproc loop3 { while ((1)) ; do echo c >> cout ; sleep 1 ; done ;}
echo PID of loop3 $loop3_PID

sleep 2
kill $loop1_PID
sleep 2
kill $loop2_PID
sleep 2
kill $loop3_PID

つまり

coproc NAME simple_command 
#or
coproc NAME { series ; of ; commands ;}

PIDは保存され、NAME_PID後でそれを使用してプロセスを終了できます。


選択する:仮想ファイル

@αГsнιιが提案したPIDを使用するのが最も正しい方法ですが、ここで別のアイデアはダミーファイルを作成することです。

 #!/bin/bash
 dummy="$(mktemp -u -p .)"
 ( while [ ! -e "$dummy" ] ; do ./async_command ; done ) &
 ...
 #condition met
 touch "$dummy"
 ...

また、このファイルを条件が満たされたことを示すインジケータとして使用することも、クリーンアップしtrapたい場合はファイルを追加することもできます。繰り返しますが、PIDによる制御を好む必要がありますが、それを乱用してループに「名前を付け」、正しいループを停止することができます。

関連情報