slojuggler2 has asked for the wisdom of the Perl Monks concerning the following question:

Suppose I do this:
#!/usr/bin/perl -w $log_file = "/home/privera/perl/logfile"; open(STDOUT, "| tee $log_file"); print "Testing 1.2.3...\n"; close(STDOUT); <lines to try below...>
If I then immediately do:
open(STDOUT, ">&SAVEOUT"); print STDOUT "I'm done\n"; close(STDOUT);
or
open(STDOUT); print "I'm done\n"; close(STDOUT);
I get:
print on closed filehandle main::STDOUT at write2.pl line 7.
What am I doing wrong? Thanks. --slojuggler2...

Originally posted as a Categorized Question.

Replies are listed 'Best First'.
Re: How do I restore STDOUT
by VSarkiss (Monsignor) on Jul 05, 2001 at 23:36 UTC
    You should always test the return value of any system call, in particular open. If you do, you'll see that both open calls are failing.

    The & in the file name is probably causing your failure, although a number of other things could be wrong (permissions, etc.)

    Originally posted as a Categorized Answer.

Re: How do I restore STDOUT
by slojuggler2 (Initiate) on Jul 06, 2001 at 20:21 UTC
    Hey everyone-- There's nothing magical about SAVEOUT. I was trying to use Cookbook 7.20 to try a solution and picked an arbitrary filehandle (SAVEOUT) to test stuff out.

    I've tried VSarkiss' idea already. The error messages were vague.

    I then tried Brent's idea:

    #!/usr/bin/perl -w $log_file = "logfile"; open(STDOUT, "| tee $log_file") or die "Can't open: $!\n"; print "Testing 1.2.3...\n"; close(STDOUT) or die "Can't close: $!\n"; open(STDOUT,'>-'); print "done\n"; close(STDOUT);
    But that didn't work. I also tried ">-" but that didn't work either...In both cases, I never got "done" printed to the STDOUT. I stumbled upon this solution, though:
    #!/usr/bin/perl -w $log_file = "logfile"; #copy file descriptor open(OLDOUT,">&STDOUT"); open(STDOUT, "| tee $log_file") or die "Can't open: $!\n"; print "Testing 1.2.3...\n"; close(STDOUT) or die "Can't close: $!\n"; #restore STDOUT open(STDOUT,">&OLDOUT"); print "done\n"; close(OLDOUT);
    Results:
    Testing 1.2.3... gets put into logfile and STDOUT done gets put on STDOUT only
    Is there a less convoluted way of doing this without having to copy file descriptors? And why does this solution work...it still puzzles me why this works...I somehow got to this solution by reading 7.20.

    Thanks everyone for your help. --slojuggler2

      That was meant by 'magical SAVOUT'. You must first copy your handle to another one to be able to copy back. In your first code you didn't do this and consequenly you copied a closed filehandle 'back'.
Re: How do I restore STDOUT
by ariels (Curate) on Jul 08, 2001 at 00:39 UTC
    Alternatively, localise STDOUT:
    { local *STDOUT; open(STDOUT, "| tee $log_file") or die; print "Testing 1...2...3...\n"; } print "done!\n";

    Originally posted as a Categorized Answer.

Re: How do I restore STDOUT
by BrentDax (Hermit) on Jul 06, 2001 at 08:00 UTC
    IIRC, open(STDOUT, '>-') will do the trick.

    Originally posted as a Categorized Answer.

Re: How do I restore STDOUT
by Anonymous Monk on Jul 06, 2001 at 01:26 UTC
    Do you think SAVEOUT has magical properties? Where do you say a thing about saving STDOUT there?

    Originally posted as a Categorized Answer.