Redirecting standard error

Hi,

I saw many examples about how to redirect standard output to - say - a
string buffer.
What about standard error? Has anybody already done this?

_gilles.

I wrote and currently use a StringIO. You can do something like this:

out, err = StringIO.new, StringIO.new

redir(out, err) do
puts “hello, world!”
$stderr.puts “ooops!”
end

p out.to_s >> “hello, world!\n”
p err.to_s >> “ooops!\n”

I use it mostly for writing test cases of things that would otherwise
hold conversation with the user. Just assign a StringIO to $stdin, in
fact, and you can simulate user input as well.

It’s far from perfect, biggest deficiency being that it always works
in `w+’ (read/write) mode, so it doesn’t prevent from doing stupid
things. It will become unnecessary when Ruby 1.8 will be out as it
contains a StringIO of its own.

If you want to have a look at it, I’ll put it online at
http://www.allruby.com/rpkg/stringio.rb by tonight.

Massimiliano

···

On Mon, Jul 08, 2002 at 10:04:04PM +0900, Gilles Filippini wrote:

I saw many examples about how to redirect standard output to - say - a
string buffer.
What about standard error? Has anybody already done this?

“Gilles Filippini” gilles.filippini@free.fr wrote in message
news:3D298A0E.35ECAE66@free.fr

Hi,

I saw many examples about how to redirect standard output to - say - a
string buffer.
What about standard error? Has anybody already done this?

_gilles.

Hi,

You can redirect standard error to file like this:

def redir(redout, rederr)
raise unless block_given?
oldout, olddef, olderr = $stdout.dup, $defout.dup, $stderr.dup
begin
f1 = File.open(redout,‘w+’)
f2 = File.open(rederr,‘w+’)
$stdout = f1.dup
$defout = f1.dup
$stderr = f2.dup
yield
ensure
f1.close
f2.close
$stdout = oldout
$defout = olddef
$stderr = olderr
end
end

redir(“/tmp/stdout”, “/tmp/stderr”) do
puts “hello, world!”
ls notexist
end

Park Heesob

Massimiliano Mirra wrote:

I saw many examples about how to redirect standard output to - say - a
string buffer.
What about standard error? Has anybody already done this?

I wrote and currently use a StringIO. You can do something like this:
[snip]
If you want to have a look at it, I’ll put it online at
http://www.allruby.com/rpkg/stringio.rb by tonight.

Thanks a lot. I’ll have a look at it.
I talked about a string buffer, but actually I’d like to redirect stderr
to something else. Thus what I need is something like a CustomIO that
can be subclassed to a StringIO or something else, with just a few
methods to rewrite.

_gilles.

···

On Mon, Jul 08, 2002 at 10:04:04PM +0900, Gilles Filippini wrote:

Massimiliano Mirra wrote:

I saw many examples about how to redirect standard output to - say - a
string buffer.
What about standard error? Has anybody already done this?

I wrote and currently use a StringIO. You can do something like this:

out, err = StringIO.new, StringIO.new

redir(out, err) do
puts “hello, world!”
$stderr.puts “ooops!”
end

p out.to_s >> “hello, world!\n”
p err.to_s >> “ooops!\n”

Unfortunately it doesn’t work as I expected. I tried this:

maison:~/test$ irb
irb(main):001:0> require “StringIO”
true
irb(main):002:0> out = StringIO.new
#<StringIO:0x402a3c64 @buffer=“”, @pos=0>
irb(main):003:0> err = StringIO.new
#<StringIO:0x402a0780 @buffer=“”, @pos=0>
irb(main):004:0> redir(out, err) do
irb(main):005:1* ls dsfgdsfgsdgsdg
irb(main):006:1> end
ls: dsfgdsfgsdgsdg: No such file or directory <= shouldn’t have been
printed here
“”
irb(main):007:0> out.to_s
“”
irb(main):008:0> err.to_s
“” <= but here
irb(main):009:0>

_gilles.

···

On Mon, Jul 08, 2002 at 10:04:04PM +0900, Gilles Filippini wrote:

Ok, someone please shed some light on this. The following works
(forget for a moment that files are closed in the procedure):

def redir(redout, rederr)
raise unless block_given?
oldout, olddef, olderr = $stdout.dup, $defout.dup, $stderr.dup
begin
$stdout = redout.dup
$defout = redout.dup
$stderr = rederr.dup
yield
ensure
redout.close
rederr.close
$stdout = oldout
$defout = olddef
$stderr = olderr
end
end

out = File.open(“/tmp/stdout”, “w+”)
err = File.open(“/tmp/stderr”, “w+”)

redir(out, err) do
puts “hello, world!”
ls notexist
end

The following does work for stdout only. It does not work for
stderr. redir is as above.

class TempIO
def initialize
@buffer = ‘’
end

def write(str)
	@buffer << str
	str.length
end

def close 
end

end

out, err = TempIO.new, TempIO.new

redir(out, err) do
puts “hello, world!”
ls notexist
end

Has a IO class to provide something else for this kind of things apart
from a write method? And even if so, where does ruby silently decide
that the given IO has no right to become stderr and grabs old stderr
back? I’m puzzled.

Massimiliano

···

On Wed, Jul 10, 2002 at 01:48:34PM +0900, Park Heesob wrote:

You can redirect standard error to file like this:

Park Heesob wrote:

“Gilles Filippini” gilles.filippini@free.fr wrote in message
news:3D298A0E.35ECAE66@free.fr

Hi,

I saw many examples about how to redirect standard output to - say - a
string buffer.
What about standard error? Has anybody already done this?

_gilles.

Hi,

You can redirect standard error to file like this:

def redir(redout, rederr)
raise unless block_given?
oldout, olddef, olderr = $stdout.dup, $defout.dup, $stderr.dup
begin
f1 = File.open(redout,‘w+’)
f2 = File.open(rederr,‘w+’)
$stdout = f1.dup
$defout = f1.dup
$stderr = f2.dup
yield
ensure
f1.close
f2.close
$stdout = oldout
$defout = olddef
$stderr = olderr
end
end

redir(“/tmp/stdout”, “/tmp/stderr”) do
puts “hello, world!”
ls notexist
end

Park Heesob

So, to redirect them to something else than a file I have then to use
redir with a pipe entry and to use a thread to transfert the pipe output
to what I want.
I’ve tried this and it does work.
Thanks a lot!
But I’m curious about why Massimiliano’s method doesn’t work for
$stderr…

_gilles.

I’ve only tested it for $stderr. Seems like commands’ stderr doesn’t
go to $stderr, though, in which case I’d be curious to know where it
goes, if anyone knows.

(Is this maybe related to the old issue of Open3 and how to get a
command’s standard error?)

Massimiliano

···

On Tue, Jul 09, 2002 at 06:04:49AM +0900, Gilles Filippini wrote:

irb(main):004:0> redir(out, err) do
irb(main):005:1* ls dsfgdsfgsdgsdg
irb(main):006:1> end
ls: dsfgdsfgsdgsdg: No such file or directory <= shouldn’t have been
printed here
“”
irb(main):007:0> out.to_s
“”
irb(main):008:0> err.to_s
“” <= but here
irb(main):009:0>

Hi,

The following does work for stdout only. It does not work for
stderr. redir is as above.

class TempIO
def initialize
@buffer = ‘’
end

def write(str)
@buffer << str
str.length
end

def close
end
end

Redirection works for IO descriptors. This TempIO has meaning
only in the process, but nothing for child processes.

out, err = TempIO.new, TempIO.new

redir(out, err) do
puts “hello, world!”
ls notexist
end

Therefore, none of stdout and stderr was redirected here, but
backticks just worked.

···

At Thu, 11 Jul 2002 02:18:56 +0900, Massimiliano Mirra wrote:


Nobu Nakada

Massimiliano Mirra wrote:

(Is this maybe related to the old issue of Open3 and how to get a
command’s standard error?)

Do you have any pointer about this issue?

_gilles.

I see! Makes sense. So is redirecting external commands output/error
a call for Open3 or is there any other chance?

Massimiliano

···

On Thu, Jul 11, 2002 at 06:55:28AM +0900, nobu.nokada@softhome.net wrote:

Redirection works for IO descriptors. This TempIO has meaning
only in the process, but nothing for child processes.

It should be all in ruby-talk archives. Check www.ruby-talk.org.

Massimiliano

···

On Wed, Jul 10, 2002 at 05:07:37AM +0900, Gilles Filippini wrote:

(Is this maybe related to the old issue of Open3 and how to get a
command’s standard error?)
Do you have any pointer about this issue?

Hi,

···

At Mon, 22 Jul 2002 20:32:21 +0900, Massimiliano Mirra wrote:

Redirection works for IO descriptors. This TempIO has meaning
only in the process, but nothing for child processes.

I see! Makes sense. So is redirecting external commands output/error
a call for Open3 or is there any other chance?

Open3 is to do it. When you need its variant, you can copy and
modify it. Unfortunately, it’s perlish and less reusable.


Nobu Nakada