Como você stderr captura, stdout, eo código de saída de uma só vez, em Perl?

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

  •  01-07-2019
  •  | 
  •  

Pergunta

É possível executar um processo externo de Perl, capturar seu stderr, stdout eo código de saída processo?

Eu pareço ser capaz de fazer combinações destes, por exemplo, uso backticks para obter stdout, IPC :: Open3 às saídas de captura, e system () para obter códigos de saída.

Como você stderr captura, stdout, eo código de saída de uma só vez?

Foi útil?

Solução

Se você reler a documentação para IPC :: Open3, você verá uma nota que você deve chamar waitpid para colher o processo filho. Depois de fazer isso, o estado deve estar disponível em $?. O valor de saída é $? >> 8. Vejo $? em perldoc perlvar .

Outras dicas

( Atualizar :. Eu atualizei a API para IO :: CaptureOutput para fazer isso ainda mais fácil)

Existem várias maneiras de fazer isso. Aqui é uma opção, usando o IO :: CaptureOutput módulo:

use IO::CaptureOutput qw/capture_exec/;

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

Esta é a função capture_exec (), mas IO :: CaptureOutput também tem uma função de captura mais geral () que pode ser usado para capturar qualquer saída Perl ou saída de programas externos. Então, se algum módulo Perl acontece a usar algum programa externo, você ainda obter o resultado.

Ele também significa que você só precisa se lembrar de uma única abordagem para capturar STDOUT e STDERR (ou fundi-las) em vez de usar IPC :: Open3 para programas externos e outros módulos para capturar saída Perl.

Se você não quer que o conteúdo de STDERR, em seguida, o comando de captura () a partir de IPC :: System :: módulo simples é quase exatamente o que você está depois:

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

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

   my $exit_value = $EXITVAL;

Você pode usar captura () com um único argumento para invocar o shell, ou vários argumentos para evitar de forma confiável o shell. Há também Capturex () que nunca chama o shell, mesmo com um único argumento.

Ao contrário do sistema e backticks comandos internos do Perl, IPC :: Sistema :: retornos simples o valor de saída de 32 bits completo no Windows. Ele também lança uma exceção detalhada se o comando não pode ser iniciado, morre a um sinal, ou retorna um valor de saída inesperado. Isto significa que para muitos programas, em vez de verificar os valores de saída, você pode confiar IPC :: System :: Simples de fazer o trabalho duro para você:

 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 :: Simples é puro Perl, não tem dependências, e funciona tanto em sistemas Unix e Windows. Infelizmente, ele não fornece uma maneira de capturar STDERR, por isso pode não ser adequado para todas as suas necessidades.

IPC :: RUN3 fornece uma interface limpa e fácil para re-encanamento tudo três filehandles comuns, mas infelizmente ele não verifica para ver se o comando foi bem sucedido, então você precisa para inspecionar $? manualmente, o que não é de todo divertido. Fornecendo uma interface pública para inspecionar $? é algo que está no meu to-do list para IPC: : System :: simples, desde inspecionar $? em uma plataforma cruzada moda não é uma tarefa que eu desejo a ninguém.

Existem outros módulos na IPC :: namespace que também pode fornecer-lhe assistência. YMMV.

Todo o melhor,

Paul

Existem três maneiras básicas de execução de comandos externos:

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

Com system(), tanto STDOUT e STDERR vai no mesmo lugar que STDOUT e STDERR, do script, a menos que o comando system() redireciona-los. Acentos graves e open() ler apenas o STDOUT de seu comando.

Você também pode chamar algo como o seguinte com aberta para redirecionar tanto STDOUT e STDERR.

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

O código de retorno é sempre armazenado em $? como observado por @ Michael Carman .

Se você está ficando muito complicado, você pode querer tentar Expect.pm. Mas isso é provavelmente um exagero se você não precisa também gerenciar o envio de dados para o processo também.

IPC: RUN3 para ser muito útil. Você pode encaminhar todas as crianças tubos para uma bola ou uma variável; muito facilmente! E código de saída serão armazenados em $ ?.

A seguir é como eu agarrei stderr que eu sabia que seria um número. A saída cmd transformações informáticos para stdout (que i canalizada para um arquivo no args usando>) e relatados como muitas transformações para STDERR.

use IPC::Run3

my $number;
my $run = run3("cmd arg1 arg2 >output_file",\undef, \undef, \$number);
die "Command failed: $!" unless ($run && $? == 0);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top