パイプラインで実行されたときにサブプロセスを起動するプログラムの動作を理解しようとしています。
このbashプログラムfork.shは、すぐに出力して返します。
_(sleep 1) &
echo 'here'
_
しかし、パイプに接続すると、読み取り側はスリープが完了するのを待つように見えます。
_$ time bash fork.sh | wc
1 1 5
real 0m1.014s
_
また、Rubyでこれを試しましたが、スリープがブロックされないようにするための追加の呼び出しがいくつかあります。
_Process.detach(fork { sleep 1 })
puts 'here'
_
_fork {
sleep 1
Process.daemon
}
puts 'here'
_
しかし、それらは同じように動作します。
これの原因(Unix、ファイル記述子など)と、パイプラインが1秒以内に戻るようにこれらのいずれかを書き直す方法があるかどうかを知りたいです。
編集:以下の答えは、Rubyの例:daemon()
呼び出しを最初に行う必要があることに気付くのに役立ちました。プロセス全体に何らかの形で適用されると思っていました。
sleep
のように)、close-on-execフラグでマークされたファイル記述子のみは閉じていますが、シェルがstdout(fd 1)にそのフラグを設定することはありません。time bash fork.sh | wc
sleep
プロセス(fork.sh
から開始)は、wc
が読み取っているパイプの書き込み終了を指すstdoutをあきらめる必要があります。 fork.sh
:
(sleep 1 >/dev/null) &
echo 'here'
この場合、sleep .. >&-
(stdoutを他の場所にリダイレクトせずに閉じる)も機能する可能性がありますが、プロセスが後でファイルを開くと、返されるファイル記述子は1 =になるため、一般的にはお勧めしません。 stdoutは、仮定を破り、バグを引き起こす可能性があります。