Как вы захватываете stderr, stdout и код выхода сразу, в Perl?
можно ли запустить внешний процесс из Perl, захватить его stderr, stdout и код выхода процесса?
кажется, я могу делать комбинации из них, например, использовать обратные палочки для получения stdout, IPC::Open3 для захвата выходов и system() для получения кодов выхода.
Как вы захватить stderr, stdout и код выхода все сразу?
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