Как вы захватываете stderr, stdout и код выхода сразу, в Perl?



можно ли запустить внешний процесс из Perl, захватить его stderr, stdout и код выхода процесса?



кажется, я могу делать комбинации из них, например, использовать обратные палочки для получения stdout, IPC::Open3 для захвата выходов и system() для получения кодов выхода.



Как вы захватить stderr, stdout и код выхода все сразу?

678   6  

6 ответов:

Если вы перечитали документацию для IPC:: Open3, вы увидите заметку, что вы должны позвонить waitpid чтобы пожать дочерний процесс. Как только вы это сделаете, статус должен быть доступен в $?. Стоимость выхода составляет $? >> 8. Видеть $? в perldoc perlvar.

(обновление: я обновил API для IO:: CaptureOutput, чтобы сделать это еще проще.)

есть несколько способов сделать это. Вот один из вариантов, используя IO:: CaptureOutput модуль:

use IO::CaptureOutput qw/capture_exec/;

my ($stdout, $stderr, $success, $exit_code) = capture_exec( @cmd );

это функция capture_exec (), но IO::CaptureOutput также имеет более общую функцию capture (), которая может использоваться для захвата вывода Perl или вывода из внешних программ. Поэтому, если какой-то модуль Perl использует какую-то внешнюю программу, вы все еще получаете выход.

Это также означает, что вам нужно запомнить только один подход к захвату STDOUT и STDERR (или их слиянию) вместо использования IPC::Open3 для внешних программ и других модулей для захвата вывода Perl.

Если вам не нужно содержимое STDERR, то команда capture () от IPC:: System:: Simple модуль почти точно, что вы после:

   use IPC::System::Simple qw(capture system $EXITVAL);

   my $output = capture($cmd, @args);

   my $exit_value = $EXITVAL;

вы можете использовать capture() с одним аргументом для вызова оболочки или несколькими аргументами, чтобы надежно избежать оболочки. Есть также capturex (), который никогда не вызывает оболочку, даже с одним аргументом.

В отличие от встроенных систем Perl и команд backticks, IPC:: System:: Simple возвращает полный 32-разрядное значение выхода в Windows. Он также выдает подробное исключение, если команда не может быть запущена, умирает до сигнала или возвращает неожиданное значение выхода. Это означает, что для многих программ, а не проверять значения выхода самостоятельно, вы можете положиться IPC:: система:: просто сделать тяжелую работу для вас:

 use IPC::System::Simple qw(system capture $EXIT_ANY);

 system( [0,1], "frobincate", @files);     # Must return exitval 0 or 1

 my @lines = capture($EXIT_ANY, "baznicate", @files);  # Any exitval is OK.

 foreach my $record (@lines) {
     system( [0, 32], "barnicate", $record);  # Must return exitval 0 or 32
 }

IPC::System:: Simple-это чистый Perl, не имеет зависимостей и работает как на Unix, так и на Windows системах. К сожалению, он не обеспечивает способ захвата STDERR, поэтому он может не подходить для всех ваших потребностей.

IPC:: Run3 обеспечивает чистый и простой интерфейс в повторной санации всех трех общих файловых хэндлов, но, к сожалению, он не проверяет, если команда была успешной, так что вам нужно будет проверить $? вручную, что совсем не весело. Предоставление публичного интерфейса для проверки $? это то, что находится на моем список для IPC:: System:: Simple, так как проверка $? в кросс-платформенной моде это не задача, которую я бы Загадай желание кому угодно.

есть и другие модули IPC:: пространство имен, которое также может предоставить вам помощь. МММ.

всего наилучшего,

Павел

существует три основных способа выполнения внешних команд:

system $cmd;        # using system()
$output = `$cmd`;       # using backticks (``)
open (PIPE, "cmd |");   # using open()

С system(), и STDOUT и STDERR будет идти в том же месте, что и скрипт STDOUT и STDERR, если перенаправляет их. Спинки и open() читать только STDOUT вашей команды.

вы также можете вызвать что-то вроде следующего с открытым для перенаправления обоих STDOUT и STDERR.

open(PIPE, "cmd 2>&1 |");

код возврата всегда хранится в $? как отмечает @Michael Carman.

Если вы получаете действительно сложно, вы можете попробовать Expect.pm но это, вероятно, излишне, если вам не нужно также управлять отправкой ввода в процесс.

нашел IPC: run3 чтобы быть очень полезным. Вы можете переслать все дочерние каналы в Глобус или переменную; очень легко! А код выхода будет храниться в $?.

ниже, как я схватил stderr, который я знал, будет число. Cmd выводит информационные преобразования в stdout (который я передал в файл в args с помощью >) и сообщил, сколько преобразований в STDERR.

use IPC::Run3

my $number;
my $run = run3("cmd arg1 arg2 >output_file",\undef, \undef, $number);
die "Command failed: $!" unless ($run && $? == 0);

Comments

    Ничего не найдено.