Reading from standard error


#1

Maybe this one has already been answered somewhere. If so, my
searching skills really suck.

How can I start a sub-process from Ruby and read its standard error
and standard output stream separately? I have tried to do it with
IO.popen, but it only reads the output stream. The Process module
doesn’t help either.

Cheers,

Thiago A.


#2

Hi !

I don’t know if this is the best way to do it, but here is how I’ll do :

rd,wt = IO.pipe # Prepare the pipe to get the output
id = fork do

Here we are in the child process

First get the system id of the pipe

$stderr.reopen(f)

Then launch your process here

exec(“prog”, arg1, …)
end

Here you can read the error output from rd

If you want to wait for the end of the other process first :

Process.waitpid(id)

Pierre

PS: I hope this works as I am not on a UNIX machine and fork does not
work :confused: However I tried the IO.reopen part and this works fine.

Thiago A. a écrit :


#3

Thiago A. wrote:

Thiago A.
require ‘open3’

stdin, stdout, stderr = Open3.popen3(
‘ruby -e “$stdout.sync = true; while (s=gets); 5.times
{$stderr.puts(s.reverse); puts s}; end”’)

t1 = Thread.new do
while (s=stderr.gets)
puts “STDERR: #{s.inspect}”
end
puts “STDERR: DONE”
end

t2 = Thread.new do
while (s=stdout.gets)
puts “STDOUT: #{s.inspect}”
end
puts “STDOUT: DONE”
end

stdin.puts “foo”
stdin.close
[t1, t2].each do |t| t.join end

The purpose of the $stdout.sync = true in the subprocess is so that you
can read the subprocess’s stdout as soon as it is written to. If all you
care about is getting all the stdout eventually, you don’t need it.