サブプロセスはパイプを開いたままにしますか?

サブプロセスはパイプを開いたままにしますか?

パイプで実行されたときに子プロセスを開始するプログラムの動作を理解しようとしています。

この 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()最初に行わなければなりません。私はそれが何らかの方法で全体のプロセスに適用されると思いました。

ベストアンサー1

  1. 子プロセスは親プロセスからすべてのファイル記述子を継承します。
  2. コマンドを実行するとき(sleepここではシェルに組み込みコマンドがないと仮定)実行時に閉じるフラグはオフですが、シェルはこれをstdout(fd 1)に設定しません。
  3. 管路リーダー次の場合にのみEOFを取得できます。みんな書き込みの終わりを指すファイル記述子がクローズされました。
time bash fork.sh | wc

sleepプロセスが開始から読み取っているパイプの書き込みの終わりをfork.sh指す標準出力を削除するようにしてください。wcfork.sh

(sleep 1 >/dev/null) &
echo 'here'

この場合sleep .. >&-(他の場所にリダイレクトせずにstdoutを閉じること)も機能しますが、プロセスが一部のファイルを開くと、返されたファイル記述子が1 = std出力になり、仮定を破る可能性があるため、通常はお勧めできません。エラーを引き起こします。

おすすめ記事