サブシェルで `sleep` を終了します。

サブシェルで `sleep` を終了します。

killBashでは、睡眠プロセスが呼び出されることを観察しました。に慣れる サブシェルから起動すると終了します。理由を理解するのに役立ちますか?

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を提供すると確信しています。)whilesleep

たとえば、次のスクリプトを考えてみましょう。

foo() {
    sleep 5 &
    echo foo
}
tmp=$(foo)
echo end.

実行には5秒かかります。

ただし、その行をsleepに変更すると、コマンドの置き換えにはリンクされなくなるsleep 5 > /dev/null &ため、スクリプトはすぐに返されます。sleepバックグラウンドスリープモードは、タイムアウトするまでバックグラウンドで実行され続けます。あなたはそれに気づく可能性が低いです。

これは特定の項目に当てはまります。コマンドの置き換え、サブシェル環境だけではありません。 ((foo)サブシェルかもしれませんが、{ foo; }またはfooここでのみ動作するはずです。)

おすすめ記事