Ruby 2.4.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > IOクラス > popen

singleton method IO.popen

popen(env = {}, command, mode = "r", opt={}) -> IO[permalink][rdoc]
popen(env = {}, command, mode = "r", opt={}) {|f| ... } -> object
popen([env = {}, cmdname, *args, execopt={}], mode = "r", opt={}) -> IO
popen([env = {}, cmdname, *args, execopt={}], mode = "r", opt={}) {|f| ... } -> object
popen([env = {}, [cmdname, arg0], *args, execopt={}], mode = "r", opt={}) -> IO
popen([env = {}, [cmdname, arg0], *args, execopt={}], mode = "r", opt={}) {|f| ... } -> object
popen(env = {}, [cmdname, *args, execopt={}], mode = "r", opt={}) -> IO
popen(env = {}, [cmdname, *args, execopt={}], mode = "r", opt={}) {|f| ... } -> object
popen(env = {}, [[cmdname, arg0], *args, execopt={}], mode = "r", opt={}) -> IO
popen(env = {}, [[cmdname, arg0], *args, execopt={}], mode = "r", opt={}) {|f| ... } -> object

サブプロセスを実行し、そのプロセスの標準入出力 との間にパイプラインを確立します。生成したパイプを IO オブジェクトとして返します。

p io = IO.popen("cat", "r+")  # => #<IO:fd 4>
io.puts "foo"
io.close_write
p io.gets                     # => "foo\n"

サブプロセスを指定する方法は2通りあります。文字列を指定する場合と配列を指定する場合です。 文字列の場合は、シェルを経由して子プロセスを実行し、 配列の場合は、シェルを経由せずに子プロセスを実行します。

シェルを経由しない場合(上のシグネチャで cmdname を含む場合)には *args がサブプロセスの引数として使われます。この場合には *args はシェルでの ワイルドカード展開などはなされません。

配列内に配列を指定することで、arg0(みせかけのプログラム名)を指定することができます。

ブロックが与えられた場合は生成した IO オブジェクトを引数にブ ロックを実行し、ブロックの実行結果を返します。ブロックの実行後、生成したパイ プは自動的にクローズされます。

p IO.popen("cat", "r+") {|io|
  io.puts "foo"
  io.close_write
  io.gets
}
# => "foo\n"

opt でプロセス起動のためのオプションや、パイプ IO オブジェクトの属性(エンコーディングや 読み書き能力)を指定することができます。 プロセス起動のためのオプションは Kernel.#spawn と、 パイプオブジェクトの属性の指定のオプションは IO.new と共通です。 つまり、 :external_encoding や :unsetenv_others が指定できます。 オプションの詳しい意味は Kernel.#spawnIO.new を参照してください。

# nkfプロセスから得られる文字列を EUC-JP と指定する
# IO.new などと共通のオプションが指定できる
IO.popen("nkf -e filename", external_encoding: "EUC-JP"){|nkf_io|
  nkf_io.read
}

これに加えて、プロセス起動のためのオプションを execopt で指定することもできます。 execopt ではエンコーディングなどは指定できません。

# 標準エラー出力を子プロセス側で標準出力にリダイレクトする
# 標準エラー出力と標準出力がマージされる
# Kernel.#spawn と共通のオプション
IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
  ls_result_with_error = ls_io.read
}

# 上と同じ、配列の外側でもオプションが指定できる
IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
  ls_result_with_error = ls_io.read
}
[PARAM] env:
環境変数を { 変数名 => 内容 } という形式の Hash で渡します。
[PARAM] command:
コマンド名を文字列で指定します。シェルを経由して実行されます。
[PARAM] cmdname:
コマンド名を文字列で指定します
[PARAM] arg0:
みせかけのコマンド名を指定します
[PARAM] args:
コマンドのパラメータを文字列で指定します
[PARAM] execopt:
プロセス実行に関するオプションを Hash で指定します。
[PARAM] mode:
オープンする IO ポートのモードを指定します。mode の詳細は Kernel.#open 参照して下さい。
[PARAM] opt:
プロセス実行やパイプのIOのエンコーディングなどを設定するオプションを指定します
[EXCEPTION] Errno::EXXX:
パイプ、あるいは子プロセスの生成に失敗した場合に発生します。
popen("-", mode = "r", opt={}) -> IO[permalink][rdoc]
popen("-", mode = "r", opt={}) {|io| ... } -> object
popen(env, "-", mode = "r", opt={}) -> IO
popen(env, "-", mode = "r", opt={}) {|io| ... } -> object

第一引数に文字列 "-" が指定された時、fork(2) を 行い子プロセスの標準入出力との間にパイプラインを確立します。 親プロセスでは IO オブジェクトを返し、子プロセスでは nil を返します。

io = IO.popen("-", "r+")
if io  # parent
  io.puts "foo"
  p io.gets                   # => "child output: foo\n"
  io.close
else   # child
  s = gets
  print "child output: " + s
  exit
end

ブロックを与えられた場合、親プロセスでは生成した IO オブジェクトを引数に ブロックを実行し、その結果を返します。ブロックの実行後、生成したパイ プは自動的にクローズされます。 子プロセスでは nil を引数にブロックを実行し終了します。

p IO.popen("-", "r+") {|io|
  if io   # parent
    io.puts "foo"
    io.gets
  else    # child
    s = gets
    puts "child output: " + s
  end
}
# => "child output: foo\n"

opt ではエンコーディングの設定やプロセス起動のためのオプションが指定できます。 IO.newKernel.#spawn で指定できるものと共通なので 詳しくはそちらを見てください。

[PARAM] env:
環境変数を { 変数名 => 内容 } という形式の Hash で渡します。
[PARAM] mode:
オープンする IO ポートのモードを指定します。mode の詳細は Kernel.#open 参照して下さい。
[PARAM] opt:
エンコーディングなどを設定するオプション引数(see IO.new)
[EXCEPTION] Errno::EXXX:
パイプ、あるいは子プロセスの生成に失敗した場合に発生します。