Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Interaction system() / $stdout ?

2 views
Skip to first unread message

Johan Holmberg

unread,
Sep 20, 2001, 3:22:25 PM9/20/01
to

Hi,

I've been trying to redirect the output of commands invoked by
"system", by changing the $stdout variable in Ruby.

I want to avoid using shell redirections in my commands:

system "echo 1 2 3 > log-file" # I want to avoid this

So instead I wrote code like this:

#----------------------------------------
system "echo In the beginning, to STDOUT I hope."

$saved_stdout = $stdout
$stdout = File.open("log-file", "w")

system "echo After redirect, to log-file I hope."

$stdout = $saved_stdout

system "echo Original restored, to STDOUT I hope."
#----------------------------------------

When I execute this code I get:

$ ruby test-system.rb
In the beginning, to STDOUT I hope.
$
$ cat log-file
After redirect, to log-file I hope.
Original restored, to STDOUT I hope.
$

So obviously, the "system" calls are affected by my change of $stdout
but only in *one* direction. I can't figure out why I get the current
behaviour. Why is the last system output also written to the
log file ?

I'm reasonably new to Ruby, but have used Perl for many years, so maybe
my expectations are influenced by how this can be done in Perl:

#----------------------------------------
system "echo In the beginning, to STDOUT I hope.";

open(SAVED_STDOUT, ">&STDOUT") || die;
open(STDOUT, "> log-file") || die;

system "echo After redirect, to log-file I hope.";

open(STDOUT, ">&SAVED_STDOUT") || die;

system "echo Original restored, to STDOUT I hope.";
#----------------------------------------

What is the best way to accomplish the same as above in Ruby ?
And what is the explanation of the current Ruby-behaviour ?

Thanks,

/Johan Holmberg

Paul Brannan

unread,
Sep 20, 2001, 3:38:06 PM9/20/01
to
On Fri, 21 Sep 2001, Johan Holmberg wrote:
> system "echo In the beginning, to STDOUT I hope."
>
> $saved_stdout = $stdout
> $stdout = File.open("log-file", "w")
>
> system "echo After redirect, to log-file I hope."
>
> $stdout = $saved_stdout
>
> system "echo Original restored, to STDOUT I hope."

Try changing:
$saved_stdout = $stdout

to:
$saved_stdout = $stdout.clone

Paul

Joseph McDonald

unread,
Sep 20, 2001, 3:39:33 PM9/20/01
to

JH> I've been trying to redirect the output of commands invoked by
JH> "system", by changing the $stdout variable in Ruby.

This appears to work:

$saved_stdout = $stdout.dup

$stdout = File.open("log-file", "w")
system "echo After redirect, to log-file I hope."

$stdout = $saved_stdout.dup

system "echo Original restored, to STDOUT I hope."

I'm not sure why that second "dup" is necessary, perhaps a guru can
elaborate or give a better solution.

regards,
-joe


Brian Marick

unread,
Sep 21, 2001, 6:09:53 PM9/21/01
to
At 02:39 PM 9/20/01, you wrote:
>This appears to work:
>
>$saved_stdout = $stdout.dup
>$stdout = File.open("log-file", "w")
>system "echo After redirect, to log-file I hope."
>$stdout = $saved_stdout.dup
>system "echo Original restored, to STDOUT I hope."
>
>I'm not sure why that second "dup" is necessary, perhaps a guru can
>elaborate or give a better solution.

I think the solution needs to be more complicated. Try closing the logfile
before restoring stdout:

$saved_stdout = $stdout.dup
$stdout = File.open("log-file", "w")
system "echo After redirect, to log-file I hope."

$stdout.close ###### New line
$stdout = $saved_stdout.dup ### this is line 5


system "echo Original restored, to STDOUT I hope."

The result of the system is this:

test4.rb:5: closed stream (IOError)

Note that the line number is the second assignment to stdout, not the
attempt to write to it.

It seems you have to stash the stream in a temp, reassign stdout, and then
close stdout:

$saved_stdout = $stdout.dup
$stdout = File.open("log-file", "w")

puts "echo After redirect, to log-file I hope."
$saved_internal_stdout = $stdout ###### New line
$stdout = $saved_stdout.dup
$saved_internal_stdout.close ###### New line
puts "echo Original restored, to STDOUT I hope."

By the way, it doesn't seem to me that the second dup is needed. Seems to
work without it. Why do you think it's needed?

This is all complicated enough that I'm going to extend my Fluid variables
package to handle it:

Fluid.redirect(["$stdout", File.open("logfile", 'w')]) {
puts "this goes to the logfile"
}
puts "this goes back to the old $stdout"

But I'd like to know if the above sequence of steps really works, or just
doesn't obviously fail.

--
Brian Marick, mar...@testing.com
www.testing.com - Software testing services and resources
www.testingcraft.com - Where software testers exchange techniques
www.visibleworkings.com - Adequate understanding of system internals


0 new messages