names=popen3
visibility=public
kind=defined

--- popen3(*cmd) -> [IO, IO, IO, Thread]
--- popen3(*cmd) {|stdin, stdout, stderr, wait_thr| ... } -> ()

外部プログラム cmd を実行し、そのプロセスの標準入力、標準出力、標準エラー
出力に接続されたパイプと実行したプロセスを待つためのスレッドを 4 要素の
配列で返します。

  stdin, stdout, stderr, wait_thr = *Open3.popen3("/usr/bin/nroff -man")

@param cmd 実行するコマンドを指定します。

@return ブロックを指定した場合はブロックの最後に評価された値を返します。
        ブロックを指定しなかった場合は標準入力、標準出力、標準エラー出
        力と実行したプロセスを待つためのスレッドに接続されたパイプを返
        します。

ブロックを指定するとパイプの配列を引数にブロックを実行し、最後にパイプ
を close します。この場合はブロックの最後の式の結果を返します。

  require 'open3'

  Open3.popen3("read stdin; echo stdout; echo stderr >&2") {|stdin, stdout, stderr, wait_thr|
    stdin.puts "stdin"
    stdin.close     # または close_write
    p stdout.read
    p stderr.read
  }
  #=> "stdout\n"
      "stderr\n"


stdin への入力が終わったらできる限り早く close か close_write
で閉じるべきです。

[UNIX系OS固有の注意] Open3 で作成した子プロセスは
[[man:wait(2)]] しなくてもゾンビになりません。

引数 cmd はそのまま [[m:Kernel.#spawn]] に渡されます。
[[m:Kernel.#spawn]]と同様に、引数リストの最初に環境変数をハッシュ形式で
指定する事ができます。

例:

  require 'open3'

  Open3.popen3({"foo" => "1", "bar" => "2"}, "env") {|i, o, e, t|
    i.close
    print o.read
  }
  #=> ...
      foo=1
      bar=2

[[m:Kernel.#spawn]]と同様に、引数リストの最後にオプションをハッシュ形式
で指定する事ができます。

例:

  require "open3"
  
  # オプションを指定した場合。
  Dir.chdir("/tmp")
  Open3.popen3("pwd", :chdir=> "/") {|i,o,e,t|
    p o.read.chomp #=> "/"
  }
  
  # オプションを指定しない場合。
  Dir.chdir("/tmp")
  Open3.popen3("pwd") {|i,o,e,t|
    p o.read.chomp #=> "/tmp"
  }

@see [[m:Kernel.#spawn]]


