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

I'm trying to redirect both STDOUT and STDERR to a file via the following code:
use IO::Handle; my $file = 'C:\Progra~1\Ethereal\output.dat'; open STDERR, ">&STDOUT"; open (OUTPUT, ">$dat") || die $!; STDOUT->fdopen(\*OUTPUT, "w") || die $!; print "This is STDOUT\n"; warn "This is a warning\n";
STDOUT gets redirected fine but STDERR still gets dumped to the screen. Any suggestions?

Replies are listed 'Best First'.
Re: how to send both STDOUT and STERR to the same file
by ikegami (Patriarch) on Oct 19, 2006 at 17:43 UTC
    This works for me:
    use IO::Handle; my $file = 'output.dat'; open(OUTPUT, ">$file") || die $!; STDOUT->fdopen(\*OUTPUT, "w") || die $!; open STDERR, ">&STDOUT"; print "This is STDOUT\n"; print STDERR "This is STDERR\n"; warn "This is a warning\n";

    Update: Cleaner:

    my $file = 'output.dat'; { open(my $fh_out, '>', $file) or die("Unable to create output file \"$file\": $!\n"); local *STDOUT = $fh_out; local *STDERR = $fh_out; print "This is STDOUT (1)\n"; print STDERR "This is STDERR (1)\n"; warn "This is a warning (1)\n"; } print "This is STDOUT (2)\n"; print STDERR "This is STDERR (2)\n"; warn "This is a warning (2)\n";

    If you want child processes to inherit STDOUT and STDERR:

    use v5.8.0; my $file = 'output.dat'; { open(my $fh_out, '>', $file) or die("Unable to create output file \"$file\": $!\n"); local *STDOUT; open(*STDOUT, '>&', $fh_out) or die("Unable to redirect STDOUT: $!\n"); local *STDERR; open(*STDERR, '>&', $fh_out) or die("Unable to redirect STDERR: $!\n"); print "This is STDOUT (1)\n"; print STDERR "This is STDERR (1)\n"; warn "This is a warning (1)\n"; } print "This is STDOUT (2)\n"; print STDERR "This is STDERR (2)\n"; warn "This is a warning (2)\n";
      Thanks ikegami, that did the trick.
Re: how to send both STDOUT and STERR to the same file
by davido (Cardinal) on Oct 19, 2006 at 17:40 UTC

    From open:

    # First, save STDERR in case you need it later. open OLDERR, ">&", \*STDERR or die "Can't dup STDERR: $!"; # Second, dupliate STDOUT, by pointing STDERR to it. open STDERR, ">&STDOUT" or die "Can't dup STDOUT: $!"; print STDOUT "My test string.\n";

    Dave

Re: how to send both STDOUT and STERR to the same file
by chrism01 (Friar) on Oct 20, 2006 at 02:15 UTC
    This works for me:
    sub create_logfile { my ( $logfile, # final logfile name $filename, # filename sans extension $filext, # filename extension $filedir # dir for logfile ); # Get filename components ($filename, $filedir, $filext) = fileparse($0, '\..*'); # Create filename $logfile = "${filedir}log/$filename.log"; # Redirect STDOUT & STDERR to named logfile open( STDOUT, ">$logfile") or die "\nUnable to open logfile $logfile: $!\n"; open( STDERR, ">>&STDOUT"); # Set autoflush on select (STDERR); $| = 1; select (STDOUT); $| = 1; }
    I set autoflush on so the last msg before it crashes actually reaches the disk file instead of being buffered in mem and possibly not reaching the file.
    paranoid logging...

    Cheers
    Chris

Re: how to send both STDOUT and STERR to the same file
by jeanluca (Deacon) on Oct 19, 2006 at 17:25 UTC
    what about
    open (STDERR, ">&STDOUT");
    LuCa
      Same thing...STDERR never gets written to the file, only the terminal
      use strict; use warnings; use IO::Handle; my $file = 'C:\Progra~1\Ethereal\output.dat'; open (STDERR, ">&STDOUT"); open (OUTPUT, ">$file") || die $!; STDOUT->fdopen(\*OUTPUT, "w") || die $!; print "This is STDOUT\n"; warn "This is a warning\n";
      Please ignore my answer, sorry!
      My test script didn't work very well, so nothing was printed, which made me a little bit to enthousiastic :)

      LuCa