¿Cómo se capturan stderr, stdout y el código de salida, todos a la vez, en Perl?

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

  •  01-07-2019
  •  | 
  •  

Pregunta

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

Parece que puedo hacer combinaciones de estos, p.use comillas invertidas para obtener la salida estándar, IPC::Open3 para capturar resultados y system() para obtener códigos de salida.

¿Cómo se capturan stderr, stdout y el código de salida al mismo tiempo?

¿Fue útil?

Solución

Si vuelves a leer la documentación de IPC::Open3, verás una nota a la que debes llamar esperar para cosechar el proceso hijo.Una vez hecho esto, el estado debería estar disponible en $?.El valor de salida es $? >> 8.Ver$? en perldoc perlvar.

Otros consejos

(Actualizar:Actualicé la API para IO::CaptureOutput para que esto sea aún más fácil).

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

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 capture() más general que se puede utilizar para capturar la salida de Perl o la salida de programas externos.Entonces, si algún módulo Perl utiliza algún programa externo, aún obtendrá el resultado.

También significa que solo necesita recordar un único enfoque 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.

Si no desea el contenido de STDERR, entonces el comando capture() de IPC::Sistema::Simple El módulo es casi exactamente lo que buscas:

   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 múltiples argumentos para evitar el shell de manera confiable.También está capturex() que nunca llama al shell, ni siquiera con un solo argumento.

A diferencia del sistema integrado de Perl y de los comandos de comillas invertidas, IPC::System::Simple devuelve el valor de salida completo de 32 bits en Windows.También genera una excepción detallada si el comando no se puede iniciar, muere ante una señal o devuelve un valor de salida inesperado.Esto significa para muchos programas, en lugar de verificar los valores de salida usted mismo, puede confiar en IPC :: System :: fácil de hacer el trabajo duro 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 que no sea adecuado para todas sus necesidades.

IPC::Ejecutar3 proporciona una interfaz limpia y sencilla para volver a conectar los tres identificadores de archivos comunes, pero desafortunadamente no verifica si el comando fue exitoso, por lo que deberá inspeccionar $?manualmente, lo cual no es nada divertido.Proporcionar una interfaz pública para inspeccionar $?es algo que está en mi lista de quehaceres para IPC::System::Simple, desde que inspecciona $?de forma multiplataforma no es una tarea que le desearía a nadie.

Hay otros módulos en el PCI:: espacio de nombres que también puede brindarle ayuda.YMMV.

Mis mejores deseos,

Pablo

Hay tres formas básicas de ejecutar comandos externos:

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

Con system(), ambos STDOUT y STDERR irá al mismo lugar que el guión. STDOUT y STDERR, a menos que el system() El comando los redirige.comillas invertidas y open() leer solo el STDOUT de tu mando.

También puedes llamar a algo como lo siguiente con open para redirigir ambos STDOUT y STDERR.

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

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

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

encontré IPC:ejecutar3 ser de mucha ayuda.Puede reenviar todas las canalizaciones secundarias a un globo o una variable;¡muy facilmente!Y el código de salida se almacenará en $?.

A continuación se muestra cómo tomé stderr, que sabía que sería un número.El cmd generó transformaciones informáticas a stdout (que canalicé a un archivo en los argumentos 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);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top