module Open3

要約

プログラムを実行し、そのプロセスの標準入力・標準出力・標準エラー出力にパイプをつなぎます。

使用例

nroff を実行してその標準入力に man ページを送り込み処理させる。 nroff プロセスの標準出力から処理結果を受け取る。

require "open3"

stdin, stdout, stderr = *Open3.popen3('nroff -man')
# こちらから書く
Thread.fork {
  File.foreach('/usr/man/man1/ruby.1') do |line|
    stdin.print line
  end
  stdin.close    # または close_write
}
# こちらから読む
stdout.each do |line|
  print line
end

目次

モジュール関数

モジュール関数

capture2(*cmd) -> [String, Process::Status][permalink][rdoc]

cmdで指定されたコマンドを実行し、そのプロセスの標準出力とプロセスの終了ステータスを表すオブジェクトを返します。

[PARAM] cmd:
実行するコマンドを指定します。
[RETURN]
実行したコマンドの標準出力と終了ステータスを表すオブジェクトを配列で返します。

指定された引数はopts[:stdin_data]とopts[:binmode]以外は全て Open3.#popen3に渡されます。opts[:stdin_data]は実行するコマンドの標準入力に渡されます。opts[:binmode]を真に指定されると内部で使用されるパイプをバイナリモードに指定します。

例:

require "open3"

# factorコマンドで与えられた数値(42)を素因数分解する。
o, s = Open3.capture2("factor", :stdin_data=>"42")
p o #=> "42: 2 3 7\n"

Open3.#popen3と同様に引数に環境変数とオプションを指定してコマンドを実行する事ができます。

[SEE_ALSO] Open3.#popen3

capture2e(*cmd) -> [String, Process::Status][permalink][rdoc]

cmdで指定されたコマンドを実行し、そのプロセスの標準出力と標準エラーを1 つの文字列にしたものとプロセスの終了ステータスを表すオブジェクトを返します。

[PARAM] cmd:
実行するコマンドを指定します。
[RETURN]
実行したコマンドの標準出力と標準エラーを1つの文字列にしたものと終了ステータスを表すオブジェクトを配列で返します。

指定された引数はopts[:stdin_data]とopts[:binmode]以外は全て Open3.#popen3に渡されます。opts[:stdin_data]は実行するコマンドの標準入力に渡されます。opts[:binmode]を真に指定されると内部で使用されるパイプをバイナリモードに指定します。

例:

require "open3"

o, s = Open3.capture2e("echo a; sort >&2", :stdin_data=>"foo\nbar\nbaz\n")
p o #=> "a\nbar\nbaz\nfoo\n"
p s #=> #<Process::Status: pid 20574 exit 0>

Open3.#popen3と同様に引数に環境変数とオプションを指定してコマンドを実行する事ができます。

[SEE_ALSO] Open3.#popen3

capture3(*cmd) -> [String, String, Process::Status][permalink][rdoc]

cmdで指定されたコマンドを実行し、そのプロセスの標準出力と標準エラー、プロセスの終了ステータスを表すオブジェクトを返します。

[PARAM] cmd:
実行するコマンドを指定します。
[RETURN]
実行したコマンドの標準出力と標準エラー、プロセスの終了ステータスを表すオブジェクトを配列で返します。

指定された引数はopts[:stdin_data]とopts[:binmode]以外は全て Open3.#popen3に渡されます。opts[:stdin_data]は実行するコマンドの標準入力に渡されます。opts[:binmode]を真に指定されると内部で使用されるパイプをバイナリモードに指定します。

例:

require "open3"

o, e, s = Open3.capture3("echo a; sort >&2", :stdin_data=>"foo\nbar\nbaz\n")
p o #=> "a\n"
p e #=> "bar\nbaz\nfoo\n"
p s #=> #<Process::Status: pid 32682 exit 0>

Open3.#popen3と同様に引数に環境変数とオプションを指定してコマンドを実行する事ができます。

[SEE_ALSO] Open3.#popen3

pipeline(*cmds) -> [Process::Status][permalink][rdoc]

指定したコマンドのリストをパイプで繋いで順番に実行します。

[PARAM] cmds:
実行するコマンドのリストを指定します。それぞれのコマンドは以下のように StringArray で指定します。 commandline にはコマンド全体(例. "nroff -man")を表す String を指定します。 options には Hash で指定します。 env には環境変数を Hash で指定します。 cmdname にはコマンド名を表す String を指定します。 1、2、3 は shell 経由で実行されます。
  1. commandline
  2. [commandline, options]
  3. [env, commandline, options]
  4. [env, cmdname, arg1, arg2, ..., options]
  5. [env, [cmdname, argv0], arg1, ..., options]
[RETURN]
実行したコマンドの終了ステータスを配列で返します。

例1:

require "open3"

fname = "/usr/share/man/man1/ruby.1.gz"
p Open3.pipeline(["zcat", fname], "nroff -man", "less")
#=> [#<Process::Status: pid 11817 exit 0>,
#    #<Process::Status: pid 11820 exit 0>,
#    #<Process::Status: pid 11828 exit 0>]

例2:

require "open3"

Open3.pipeline([{"LANG"=>"C"}, "env"], ["grep", "LANG"], "less")

[SEE_ALSO] Open3.#popen3

pipeline_r(*cmds) -> [IO, [Thread]][permalink][rdoc]
pipeline_r(*cmds) {|last_stdout, wait_thrs| ... } -> ()

指定したコマンドのリストをパイプで繋いで順番に実行します。最後のコマンドの標準出力を受けとる事ができます。

[PARAM] cmds:
実行するコマンドのリストを指定します。それぞれのコマンドは以下のように StringArray で指定します。 commandline にはコマンド全体(例. "nroff -man")を表す String を指定します。 options には Hash で指定します。 env には環境変数を Hash で指定します。 cmdname にはコマンド名を表す String を指定します。 1、2、3 は shell 経由で実行されます。
  1. commandline
  2. [commandline, options]
  3. [env, commandline, options]
  4. [env, cmdname, arg1, arg2, ..., options]
  5. [env, [cmdname, argv0], arg1, ..., options]
[RETURN]
ブロックを指定した場合はブロックの最後に評価された値を返します。ブロックを指定しなかった場合は最後に実行するコマンドの標準出力、実行したプロセスを待つためのスレッドの配列を配列で返します。

例:

require "open3"

Open3.pipeline_r("yes", "head -10") {|r, ts|
  p r.read      #=> "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"
  p ts[0].value #=> #<Process::Status: pid 24910 SIGPIPE (signal 13)>
  p ts[1].value #=> #<Process::Status: pid 24913 exit 0>
}

[SEE_ALSO] Open3.#popen3

pipeline_rw(*cmds) -> [IO, IO, [Thread]][permalink][rdoc]
pipeline_rw(*cmds) {|first_stdin, last_stdout, wait_thrs| ... } -> ()

指定したコマンドのリストをパイプで繋いで順番に実行します。最初のコマンドの標準入力に書き込む事も最後のコマンドの標準出力を受けとる事もできます。

[PARAM] cmds:
実行するコマンドのリストを指定します。それぞれのコマンドは以下のように StringArray で指定します。 commandline にはコマンド全体(例. "nroff -man")を表す String を指定します。 options には Hash で指定します。 env には環境変数を Hash で指定します。 cmdname にはコマンド名を表す String を指定します。 1、2、3 は shell 経由で実行されます。
  1. commandline
  2. [commandline, options]
  3. [env, commandline, options]
  4. [env, cmdname, arg1, arg2, ..., options]
  5. [env, [cmdname, argv0], arg1, ..., options]
[RETURN]
ブロックを指定した場合はブロックの最後に評価された値を返します。ブロックを指定しなかった場合は最初に実行するコマンドの標準入力と最後に実行するコマンドの標準出力、実行したプロセスを待つためのスレッドの配列を配列で返します。

例:

require "open3"

Open3.pipeline_rw("sort", "cat -n") {|stdin, stdout, wait_thrs|
  stdin.puts "foo"
  stdin.puts "bar"
  stdin.puts "baz"

  # sortコマンドにEOFを送る。
  stdin.close

  # stdinに渡した文字列をsortコマンドが並べ替えたものに、catコマンド
  # が行番号を付けた文字列が表示される。
  p stdout.read   #=> "     1\tbar\n     2\tbaz\n     3\tfoo\n"
}

[SEE_ALSO] Open3.#popen3

pipeline_start(*cmds) -> [Thread][permalink][rdoc]
pipeline_start(*cmds) {|wait_thrs| ... } -> ()

指定したコマンドのリストをパイプで繋いで順番に実行します。

[PARAM] cmds:
実行するコマンドのリストを指定します。それぞれのコマンドは以下のように StringArray で指定します。 commandline にはコマンド全体(例. "nroff -man")を表す String を指定します。 options には Hash で指定します。 env には環境変数を Hash で指定します。 cmdname にはコマンド名を表す String を指定します。 1、2、3 は shell 経由で実行されます。
  1. commandline
  2. [commandline, options]
  3. [env, commandline, options]
  4. [env, cmdname, arg1, arg2, ..., options]
  5. [env, [cmdname, argv0], arg1, ..., options]
[RETURN]
ブロックを指定した場合はブロックの最後に評価された値を返します。ブロックを指定しなかった場合は実行したプロセスを待つためのスレッドの配列を返します。

例:

require "open3"

# xeyesを10秒だけ実行する。
Open3.pipeline_start("xeyes") {|ts|
  sleep 10
  t = ts[0]
  Process.kill("TERM", t.pid)
  p t.value #=> #<Process::Status: pid 911 SIGTERM (signal 15)>
}

[SEE_ALSO] Open3.#popen3

pipeline_w(*cmds) -> [IO, [Thread]][permalink][rdoc]
pipeline_w(*cmds) {|first_stdin, wait_thrs| ... } -> ()

指定したコマンドのリストをパイプで繋いで順番に実行します。最初のコマンドの標準入力に書き込む事ができます。

[PARAM] cmds:
実行するコマンドのリストを指定します。それぞれのコマンドは以下のように StringArray で指定します。 commandline にはコマンド全体(例. "nroff -man")を表す String を指定します。 options には Hash で指定します。 env には環境変数を Hash で指定します。 cmdname にはコマンド名を表す String を指定します。 1、2、3 は shell 経由で実行されます。
  1. commandline
  2. [commandline, options]
  3. [env, commandline, options]
  4. [env, cmdname, arg1, arg2, ..., options]
  5. [env, [cmdname, argv0], arg1, ..., options]
[RETURN]
ブロックを指定した場合はブロックの最後に評価された値を返します。ブロックを指定しなかった場合は最初に実行するコマンドの標準入力、実行したプロセスを待つためのスレッドの配列を配列で返します。

例:

require "open3"

Open3.pipeline_w("bzip2 -c", :out=>"/tmp/hello.bz2") {|w, ts|
  w.puts "hello"
}

[SEE_ALSO] Open3.#popen3

popen2(*cmd) -> [IO, IO, Thread][permalink][rdoc]
popen2(*cmd) {|stdin, stdout, wait_thr| ... } -> ()

cmdで指定されたコマンドを実行し、そのプロセスの標準入力・標準出力にパイプをつなぎます。Open3.popen3に似ていますが、標準エラーを扱いません。

[PARAM] cmd:
実行するコマンドを指定します。
[RETURN]
ブロックを指定した場合はブロックの最後に評価された値を返します。ブロックを指定しなかった場合は標準入力、標準出力に接続されたパイプと実行したプロセスを待つためのスレッドを返します。

Open3.#popen3と同様に引数に環境変数とオプションを指定してコマンドを実行する事ができます。

[SEE_ALSO] Open3.#popen3

popen2e(*cmd) -> [IO, IO, Thread][permalink][rdoc]
popen2e(*cmd) {|stdin, stdout_and_stderr, wait_thr| ... } -> ()

cmdで指定されたコマンドを実行し、そのプロセスの標準入力・標準出力と標準エラーにパイプをつなぎます。Open3.popen3に似ていますが、標準出力と標準エラーが1つの変数で扱われます。

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

Open3.#popen3と同様に引数に環境変数とオプションを指定してコマンドを実行する事ができます。

[SEE_ALSO] Open3.#popen3

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

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

require 'open3'
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 で作成した子プロセスは wait(2) しなくてもゾンビになりません。

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

例:

require 'open3'

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

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_ALSO] Kernel.#spawn