Search code examples
perlsystemstdoutstderrhttp-redirect

How to redirect STDOUT and STDERR to a variable


I want to redirect STDERR and STDOUT to a variable. I did this.

close(STDOUT);
close(STDERR);

my $out;
open(STDOUT, ">>", \$out);
open(STDERR, ">>", \$out);

for(1..10)
{
    print "print\n"; # this is ok. 
    warn "warn\n"; # same
    system("make"); # this is lost. neither in screen nor in variable.
}

The problem with system. I want the output of this call to be captured too.


Solution

  • Are you seeking to capture the output in a variable? If so, you have use backticks or qx{} with appropriate redirection. For example, you could use:

    #/usr/bin/env perl
    use strict;
    use warnings;
    
    # Ensure we have a way to write messages
    open my $fh, '>', "output" or die;
    
    close(STDOUT);
    close(STDERR);
    
    my $out;
    open(STDOUT, ">>", \$out) or do { print $fh, "failed to open STDOUT ($!)\n"; die };
    open(STDERR, ">>", \$out) or do { print $fh, "failed to open STDERR ($!)\n"; die };
    
    foreach my $i (1..10)
    {
        print "print $i\n"; 
        warn "warn $i\n";
        my $extra = qx{make pth$i 2>&1};
        print $fh "<<$i>><<$out>><<$extra>>\n";
    }
    

    (I happen to have programs pth1, pth2 and pth3 in the directory - they were made OK; pth4 and above write errors to stderr; the redirection was necessary.)

    You should always check the success of operations such as open().

    Why is this necessary? Because writing to a variable requires the cooperation of the process doing the writing - and make doesn't know how to cooperate.