你如何捕获标准错误,stdout和退出代码一下子,在Perl?你如何捕获标准错误,stdout和退出

2019-06-17 10:36发布

是否有可能在Perl运行外部进程,捕获它的标准错误,stdout和的进程退出代码?

我似乎能够做这些组合,例如使用反引号获取标准输出,IPC :: Open3捕获输出,以及系统()来获取退出代码。

你如何捕获标准错误,stdout和退出代码一下子?

Answer 1:

如果重新读取IPC :: Open3的文件,你会看到一张纸条,你应该调用waitpid函数来获得子进程。 一旦你这样做,状态应在使用$? 。 出口值为$? >> 8 $? >> 8 。 见$? 在参阅perldoc perlvar 。



Answer 2:

更新 :我更新的IO :: CaptureOutput的API,使这个更容易。)

有几种方法可以做到这一点。 这里有一个选项,使用IO :: CaptureOutput模块:

use IO::CaptureOutput qw/capture_exec/;

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

这是capture_exec()函数,但是IO :: CaptureOutput还具有可以被用来捕捉是Perl输出或输出从外部程序更一般的捕获()函数。 所以,如果一些Perl模块,发生使用一些外部程序,你仍然可以获得输出。

这也意味着你只需要记住一个单一的方法来捕捉STDOUT和STDERR(或合并它们),而不是使用IPC :: Open3外部程序等模块捕捉Perl的输出。



Answer 3:

如果你不希望STDERR的内容,然后从捕获()命令IPC ::系统::简单的模块几乎完全你追求的:

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

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

   my $exit_value = $EXITVAL;

您可以使用捕获()的一个参数来调用外壳,或多个参数,以可靠地避免外壳。 还有capturex()从未调用外壳,即使一个参数。

与Perl的内置系统和反引号命令,IPC ::系统::简单返回Windows下的完整的32位退出值。 这也将引发命令不能启动一个详细的异常,死了一个信号,或返回一个意外的退出值。 这意味着许多程序,而不是检查出口值自己,你可以依靠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 ::系统::简单是纯Perl的,没有依赖,并适用于Unix和Windows系统。 不幸的是,它不提供捕获STDERR的方式,所以它可能不适合您的所有需求。

IPC :: RUN3提供一个清洁,简单的界面到重新水暖三个共同文件句柄,但遗憾的是它不检查,看是否该命令是成功的,所以您需要检查$? 手动,这一点也不好玩。 提供检查$一个公共接口? 是什么这是我的待办事项列表的IPC ::系统::简单,因为检查$? 在跨平台的方式是不是我在任何人身上的任务。

还有其他模块IPC ::命名空间也可以为您提供帮助。 因人而异。

祝一切顺利,

保罗



Answer 4:

有执行外部指令的三种基本方式:

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

随着system()这两个STDOUT和STDERR会去同一个地方为脚本的STDOUTSTDERR,除非system()命令重定向他们。 反引号和open()只读的STDOUT你的命令。

你也可以拨打像张开以下重定向都STDOUTSTDERR

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

返回代码总是存储在$? 如指出@迈克尔卡曼 。



Answer 5:

如果你变得非常复杂,你可能会想尝试Expect.pm。 但是,这可能是矫枉过正,如果你不也需要管理传送输入过程中也是如此。



Answer 6:

我发现IPC:RUN3是非常有帮助的。 你可以把所有的孩子管到水珠或变量; 非常简单地! 和退出代码将被存储在$?

下面是我如何抓住标准错误,我知道这将是一个数字。 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);


文章来源: How do you capture stderr, stdout, and the exit code all at once, in Perl?