Как перенаправить STDOUT и STDERR на переменную

Я хочу, чтобы перенаправить STDERR и STDOUT переменной. Я сделал это.

close(STDOUT);
close(STDERR);

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

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

проблема с system. Я хочу, чтобы результат этого вызова также был захвачен.

5 ответов


вы ищете, чтобы захватить выходные данные в переменной? Если да, то у вас есть backticks или qx{} С соответствующим перенаправлением. Например, вы можете использовать:

#/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";
}

(у меня есть программы pth1, pth2 и pth3 в каталоге - они были сделаны нормально; pth4 и выше пишут ошибки в stderr; перенаправление было необходимо.)

вы всегда должны проверять успешность таких операций, как open().

Почему это необходимо? Потому что писать переменная требует сотрудничества процесса, делающего запись-и make не знает, как сотрудничать.


использовать Capture:: Tiny!


причина этого заключается в том, что STDOUT и STDERR "filehandles" являются не эквивалентно дескрипторам stderr и stdout, предоставляемым оболочкой двоичному файлу perl. Для того, чтобы достичь того, что вы хотите, вы должны использовать открыть вместо system


почему use IPC::Open3?


есть несколько способов перенаправление и восстановление STDOUT. Некоторые из них тоже работают со STDERR. Вот два моих любимых:

используя select:

my $out;
open my $fh, ">>", $out;
select $fh;
print "written to the variable\n";
select STDOUT;
print "written to original STDOUT\n";

используя local:

my $out
do {
    local *STDOUT;
    open STDOUT, ">>", $out;
    print "written to the variable\n";
};
print "written to original STDOUT\n";

наслаждайтесь.