Python のサブプロセス Popen.communicate() で実行できるのと同様の方法で、spawn (複数の同時子プロセス用) を使用して Ruby で外部プロセスを実行し、stdout または stderr を文字列に収集したいと考えています。
:out/:err を新しい StringIO オブジェクトにリダイレクトしようとしましたが、ArgumentError が生成され、$stdxxx を一時的に再定義すると、子プロセスの出力が混同されます。
Python のサブプロセス Popen.communicate() で実行できるのと同様の方法で、spawn (複数の同時子プロセス用) を使用して Ruby で外部プロセスを実行し、stdout または stderr を文字列に収集したいと考えています。
:out/:err を新しい StringIO オブジェクトにリダイレクトしようとしましたが、ArgumentError が生成され、$stdxxx を一時的に再定義すると、子プロセスの出力が混同されます。
popenが気に入らない場合は、次の方法があります。
r, w = IO.pipe
pid = Process.spawn(command, :out => w, :err => [:child, :out])
w.close
...
pid, status = Process.wait2
output = r.read
r.close
とにかく、 String オブジェクトに直接リダイレクトすることはできません。上記のコードのように、せいぜいそれを IO オブジェクトに送信してから、そこから読み取ることができます。
なぜあなたが必要なのspawn
ですか?Windows を使用していない場合は、次のように使用できpopen*
ますpopen4
。
require "open4"
pid, p_i, p_o, p_e = Open4.popen4("ls")
p_i.close
o, e = [p_o, p_e].map { |p| begin p.read ensure p.close end }
s = Process::waitpid2(pid).last
Ruby docs からはできないようですが、これを行うことができます:
spawn("ls", 0 => ["/tmp/ruby_stdout_temp", "w"])
stdoutStr=File.read("/tmp/ruby_stdout_temp")
標準エラーでも同じことができます。または、それをしたくなくても構わない場合は、次のようにしますpopen
。
io=IO.popen("ls")
stdout=io.read