是否可以从Perl运行外部进程,捕获其stderr,stdout和进程退出代码?
我似乎能够组合这些,例如使用反引号来获取stdout,使用IPC :: Open3来捕获输出,使用system()来获取退出代码.
你如何一次捕获stderr,stdout和退出代码?
(更新:我更新了IO :: CaptureOutput的API,使其更加简单.)
有几种方法可以做到这一点.这是一个选项,使用IO :: CaptureOutput模块:
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输出.
如果您重读了IPC :: Open3的文档,您将看到一条注释,您应该调用waitpid来获取子进程.完成此操作后,状态应该可用$?
.退出值是$? >> 8
.见
$?
perldoc perlvar.
如果你不想要STDERR的内容,那么来自IPC :: System :: Simple模块的capture()命令几乎就是你所追求的:
use IPC::System::Simple qw(capture system $EXITVAL); my $output = capture($cmd, @args); my $exit_value = $EXITVAL;
您可以使用带有单个参数的capture()来调用shell,也可以使用多个参数来可靠地避免使用shell.还有capturex(),它永远不会调用shell,即使只有一个参数.
与Perl的内置系统和反引号命令不同,IPC :: System :: Simple在Windows下返回完整的32位退出值.如果命令无法启动,信号死亡或返回意外退出值,它也会抛出详细的异常.这意味着对于许多程序而言,您可以依靠IPC :: System :: Simple为您做出艰苦的工作,而不是自己检查退出值:
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的方法,因此它可能不适合您的所有需求.
IPC :: Run3提供了一个干净简单的界面来重新管理所有三个常见的文件句柄,但不幸的是它没有检查命令是否成功,所以你需要检查$?手动,这一点都不好玩.提供检查$的公共界面?因为检查$?是我在 TM :: System :: Simple 的待办事项清单上的东西.跨平台的方式不是我希望任何人的任务.
IPC ::名称空间中还有其他模块也可以为您提供帮助.因人而异.
祝一切顺利,
保罗
运行外部命令有三种基本方法:
system $cmd; # using system() $output = `$cmd`; # using backticks (``) open (PIPE, "cmd |"); # using open()
有了system()
,两者STDOUT
和STDERR将与脚本相同STDOUT
,STDERR,
除非system()
命令重定向它们.反引号并open()
只读取STDOUT
你的命令.
你也可以拨打像张开以下重定向都STDOUT
和STDERR
.
open(PIPE, "cmd 2>&1 |");
返回代码始终存储在@Michael Carman$?
所指出的位置.