Как одновременно захватить stderr, stdout и код выхода в Perl?

StackOverflow https://stackoverflow.com/questions/109124

  •  01-07-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

Другие советы

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

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

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::Система::Простой модуль почти в точности соответствует тому, что вам нужно:

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

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

   my $exit_value = $EXITVAL;

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

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

 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, поэтому может не подойти для всех ваших нужд.

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

Есть и другие модули МПК:: пространство имен, которое также может оказать вам помощь.ЮММВ.

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

Павел

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

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

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

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

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

Код возврата всегда хранится в $? как отметил @Майкл Карман.

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

я нашел МПК: запуск3 быть очень полезным.Вы можете перенаправить все дочерние каналы в glob или переменную;очень легко!И код выхода будет храниться в $?.

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

use IPC::Run3

my $number;
my $run = run3("cmd arg1 arg2 >output_file",\undef, \undef, \$number);
die "Command failed: $!" unless ($run && $? == 0);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top