perl stdout exit-code

¿Cómo capturar stderr, stdout y el código de salida de una sola vez en Perl?



exit-code (6)

( Actualización : actualicé la API para IO :: CaptureOutput para hacer esto aún más fácil).

Hay varias formas de hacer esto. Aquí hay una opción, usando el módulo IO::CaptureOutput :

use IO::CaptureOutput qw/capture_exec/; my ($stdout, $stderr, $success, $exit_code) = capture_exec( @cmd );

Esta es la función capture_exec (), pero IO :: CaptureOutput también tiene una función de captura () más general que se puede utilizar para capturar la salida Perl o la salida de programas externos. Entonces, si algún módulo de Perl utiliza algún programa externo, aún obtendrá la salida.

También significa que solo necesita recordar un enfoque único para capturar STDOUT y STDERR (o fusionarlos) en lugar de usar IPC :: Open3 para programas externos y otros módulos para capturar resultados de Perl.

¿Es posible ejecutar un proceso externo desde Perl, capturar su stderr, stdout Y el código de salida del proceso?

Me parece ser capaz de hacer combinaciones de estos, por ejemplo, utilizar los trazos atrás para obtener stdout, IPC :: Open3 para capturar salidas, y system () para obtener los códigos de salida.

¿Cómo captura stderr, stdout y el código de salida de una sola vez?


Encontré IPC:run3 para ser muy útil. Puede reenviar todas las tuberías secundarias a un globo o a una variable; ¡muy facilmente! Y el código de salida se almacenará en $ ?.

A continuación se muestra cómo agarré stderr, que sabía que sería un número. El cmd dio como resultado transformaciones informáticas a stdout (que canalicé a un archivo en args usando>) e informó cuántas transformaciones a STDERR.

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


Hay tres formas básicas de ejecutar comandos externos:

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

Con system() , tanto STDOUT como STDERR irán al mismo lugar que STDOUT y STDERR, menos que el comando system() redirija. Backticks y open() solo leen el STDOUT de su comando.

También puede llamar a algo como lo siguiente con abierto para redirigir STDOUT y STDERR .

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

El código de retorno siempre se almacena en $? como lo señaló @Michael Carman .


Si no quiere los contenidos de STDERR, entonces el comando capture () del IPC::System::Simple es casi exactamente lo que busca:

use IPC::System::Simple qw(capture system $EXITVAL); my $output = capture($cmd, @args); my $exit_value = $EXITVAL;

Puede usar capture () con un solo argumento para invocar el shell o varios argumentos para evitar el shell de manera confiable. También hay capturex () que nunca llama al shell, incluso con un solo argumento.

A diferencia de los comandos incorporados del sistema y de los backticks de Perl, IPC :: System :: Simple devuelve el valor de salida completo de 32 bits en Windows. También arroja una excepción detallada si el comando no puede iniciarse, muere a una señal o devuelve un valor de salida inesperado. Esto significa que para muchos programas, en lugar de verificar los valores de salida usted mismo, puede confiar en IPC :: System :: Simple para que haga el trabajo por usted:

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 es Perl puro, no tiene dependencias y funciona tanto en sistemas Unix como Windows. Desafortunadamente, no proporciona una forma de capturar STDERR, por lo que puede no ser adecuado para todas sus necesidades.

IPC::Run3 proporciona una interfaz limpia y fácil para volver a conectar las tres manejadoras de archivos comunes, pero desafortunadamente no verifica si el comando fue exitoso, ¿por lo que necesitará inspeccionar $? manualmente, lo cual no es para nada divertido. ¿Proporciona una interfaz pública para inspeccionar $? es algo que está en mi lista de cosas por hacer para IPC :: System :: Simple, desde la inspección de $? en una plataforma multiplataforma no es una tarea que desearía a nadie.

Hay otros módulos en el espacio de nombres IPC:: que también pueden proporcionarle asistencia. YMMV.

Todo lo mejor,

Pablo


Si te estás volviendo realmente complicado, quizás quieras probar Expect.pm. Pero eso probablemente sea excesivo si no necesita administrar el envío de entradas al proceso también.


Si vuelve a leer la documentación de IPC :: Open3, verá una nota que debe llamar a waitpid para obtener el proceso secundario. Una vez que haga esto, el estado debería estar disponible en $? . El valor de salida es $? >> 8 $? >> 8 . Ver $? en perldoc perlvar .