search
LoginSignup
7

More than 5 years have passed since last update.

posted at

updated at

IO.popenメソッドで標準エラー出力を取得するには

IO.popen では標準出力しか取得出来ない?

Q. FFmpeg や rtmpdump ではログが標準エラー出力に出力されます。IO.popen の使い方をググったときに見たのですが、標準出力しか取得出来なさそう。これらのコマンドのログを利用したいときにはその他の手段を使わないとダメなんでしょうね。
A. いいえ、そんなことはありません。標準エラー出力も取得出来ます1
IO.popen の普段の使い方(オプションなし)だと標準出力しか取得出来ないのですが、オプションで指定すると標準エラー出力を取得出来ます。

IO.popen(command, :err => [:child, :out])
IO.popen(command, :err => [:child, :out]) { |pipe| ... }

なお、ブロックパラメータ pipeIO インスタンスなので、文字出力として扱う場合には、さらに IO#each_lineIO#each_char で扱いましょう。
標準エラー出力を扱う場合には Open3 ライブラリを使うことが多いようですが、わざわざ require 'open3' しなくても IO.popen ですむのであれば、そのほうが簡単でいいのではないでしょうか。

ファイルディスクリプタの書き方

ファイルデスクリプタを表すためには、以下が利用できます。
:in - 標準入力, ファイルデスクリプタ0
:out - 標準出力, ファイルデスクリプタ1
:err - 標準エラー出力, ファイルデスクリプタ2
整数 - 指定した整数が表すファイルデスクリプタ
IO - IO#fileno で表されるファイルデスクリプタ
module function Kernel.#spawn (Ruby 2.2.0)

なので、以下のどれであっても同じ意味です。理解しやすいものであればどれでもいいのではないでしょうか。

IO.popen(command, :err => [:child, :out]) { |pipe| ... }
IO.popen(command, err: [:child, :out]) { |pipe| ... }
IO.popen(command, 2 => [:child, 1]) { |pipe| ... }
IO.popen(command, $stderr => [:child, $stdout]) { |pipe| ... }
IO.popen(command, STDERR=> [:child, STDOUT]) { |pipe| ... }

おまけ:IO.popen のオプションで便利そうなもの

以下の引用では Kernel.#spawn での解説ですが、IO.popen でも使えます。

「:chdir」で子プロセスのカレントディレクトリを変更できます。

pid = spawn(command, :chdir=>"/var/tmp")

「:umask」で子プロセスの umask を指定できます。

pid = spawn(command, :umask=>077)

感想

IO クラス(や File クラス)は奥が深い。

詳細情報へのリンク

この記事は IO.popenメソッドで標準エラー出力を取得するには - 別館 子子子子子子(ねこのここねこ) の要約です。


  1. Ruby 1.9以降対応。もう1.8系を使ってるひとは居ないでしょうけど。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
7