
バックグラウンド プロセス (スクリプト内で先に起動) が完了するまでループしようとしています。簡単に再現できるテスト ケースは次のとおりです。
ping -c 10 localhost &>/dev/null &
コマンドラインでは、ループできますwhile [[ -n $(jobs) ]]
(while$(jobs)
は null ではありません)。
$ ping -c 10 localhost &>/dev/null &
[1] 19078
$ while [[ -n $(jobs) ]]; do echo -n .; sleep 1; done
.........[1]+ Done ping -c 5 localhost &> /dev/null
ただし、スクリプト内の同じ 2 行は、.
を押すまで sを出力し続けますCtrl-C
。
jobs
奇妙なことに、ループ内で呼び出すと、スクリプトは期待どおりに終了します。
$ ./background-ping.sh
.[1]+ Running ping -c 5 localhost &> /dev/null &
.[1]+ Running ping -c 5 localhost &> /dev/null &
.[1]+ Running ping -c 5 localhost &> /dev/null &
.[1]+ Running ping -c 5 localhost &> /dev/null &
.[1]+ Done ping -c 5 localhost &> /dev/null
バックグラウンド ジョブが完了したかどうかを確認する他の方法 ( のチェックなど) があることは承知していますが、チェックが期待どおりに機能しない/proc
理由を知りたいです。jobs
答え1
あなたの問題を理解しているなら、スクリプト内で 2 行が止まらないということです。
私が作ったのは次のものです:
ping -c 5 google.com &>/dev/null &
while [[ -n $(jobs -r) ]]; do echo -n "."; sleep 1; done
jobs -r
実行中のプロセスをチェックし、スクリプトの呼び出しが期待どおりに機能し、ping が完了するとスクリプトが停止します。
編集: スクリプトでは親プロセスは実行中のプロセスとして知られているので、jobs
実行中のプロセスがあると考え続けるべきだと思います。これは仮説です。
それが答えですか?(あるいは、私があなたの言っていることを本当に理解していないのかもしれません。私の英語が下手なのが問題かもしれません...)
答え2
このような問題が発生した場合は、常に変数を印刷して何が起こっているかを把握するようにしてください。この場合、jobs
完了したジョブも返されます。これを実行すると:
ping -c 5 localhost &>/dev/null &
while [[ -n $(jobs | tee -a temp) ]]; do
echo -n .;
sleep 1;
done
次のような出力が表示されますtemp
。
[1]+ Running ping -c 5 localhost &> /dev/null &
[1]+ Running ping -c 5 localhost &> /dev/null &
[1]+ Running ping -c 5 localhost &> /dev/null &
[1]+ Running ping -c 5 localhost &> /dev/null &
[1]+ Done ping -c 5 localhost &> /dev/null
[1]+ Done ping -c 5 localhost &> /dev/null
[1]+ Done ping -c 5 localhost &> /dev/null
[1]+ Done ping -c 5 localhost &> /dev/null
[1]+ Done ping -c 5 localhost &> /dev/null
[...]
したがって、ここでの出力はjobs
決して空にはなりません。ジョブが終了しても、メッセージjobs
は返されますDone
。これが、Metal3d のソリューションが機能jobs -r
した理由です。
さらに混乱するのは、なぜループ内で実行すると正しく動作するのかということです。答えは、別のサブシェルで実行されるjobs
という事実と関係があると思われますが、詳細についてはよくわかりません。while [[ -n $(jobs) ]]
jobs
質問を投稿しました誰かが興味を持っているなら、これについてU&Lについて。
答え3
wait
バックグラウンドジョブが停止するのを待つコマンドを使用することができます
例:
$ ping -c 10 localhost &>/dev/null &
[29787]
$ wait
[1]+ Done ping -c 10 localhost &>/dev/null
wait コマンドはブロックし、ping
終了するとプロンプトが解放され、メッセージが出力されます。
いくつかのコマンドで使用できます:
$ ping -c 5 localhost &>/dev/null & ping -c 5 facebook.com &>/dev/null &
[1] 29867
[2] 29868
$ wait
[1]- Done ping -c 5 localhost &>/dev/null
[2]+ Done ping -c 5 facebook.com &>/dev/null