Как перенаправить STDOUT и STDERR в переменную - PullRequest
11 голосов
/ 11 декабря 2010

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

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.
}

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

Ответы [ 5 ]

13 голосов
/ 11 декабря 2010

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

4 голосов
/ 11 декабря 2010

Вы хотите записать вывод в переменную? Если это так, вы должны использовать 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 не знает, как сотрудничать.

3 голосов
/ 10 июля 2014

Существует несколько способов перенаправить и восстановить 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";

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

2 голосов
/ 11 декабря 2010

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

1 голос
/ 11 декабря 2010

Почему бы не use IPC::Open3?

...