kill
Bashでは、睡眠プロセスが呼び出されることを観察しました。に慣れる サブシェルから起動すると終了します。理由を理解するのに役立ちますか?
function foo () {
# Start a loop with `sleep` in the background
while true; do
>&2 echo looping
sleep 5
done &
# Wait for user input, then kill the "sleep" loop
loop_id=$!
read -p 'press enter' DUMMY
kill $loop_id
}
echo $(foo) # Call foo within a subshell
echo "DONE"
最後の行がサブシェルを使用しているかどうかによって、2つの異なる状況が発生する可能性があります。
- サブシェル呼び出しを使用して呼び出しを
echo $(foo)
満たすためにEnterキーを押すと、read
スクリプトはsleep
最後まで終了しません。 foo
関数を呼び出す代わりに just を使用すると、$(foo)
Enter キーを押すとすぐにスクリプトが終了します。
このおもちゃの例がありますが、実際の作業では標準出力をシェルfoo
変数としてキャプチャしたいので、できるだけ早くサブシェルを終了したいと思います。 2つの目標を同時に達成する方法はありますか?
ベストアンサー1
コマンド置換を使用すると、$(foo)
シェルはコマンド置換へのすべての入力が受信されるのを待ちます。実行中のsleep
ファイル記述子(おそらくパイプ)のコピーは、シェルがコマンド代替出力を読み取る場所にリンクされます。 (また、内部PIDではなく$!
ループを実行するシェルのPIDを提供すると確信しています。)while
sleep
たとえば、次のスクリプトを考えてみましょう。
foo() {
sleep 5 &
echo foo
}
tmp=$(foo)
echo end.
実行には5秒かかります。
ただし、その行をsleep
に変更すると、コマンドの置き換えにはリンクされなくなるsleep 5 > /dev/null &
ため、スクリプトはすぐに返されます。sleep
バックグラウンドスリープモードは、タイムアウトするまでバックグラウンドで実行され続けます。あなたはそれに気づく可能性が低いです。
これは特定の項目に当てはまります。コマンドの置き換え、サブシェル環境だけではありません。 ((foo)
サブシェルかもしれませんが、{ foo; }
またはfoo
ここでのみ動作するはずです。)