2012-01-04 51 views
4

我想在我的Perl脚本中执行一个外部命令,将stdout和stderr的输出放入我选择的$variable中,并获得命令的退出代码放入$?变量中。从外部* nix命令获得STDOUT,STDERR和响应代码perl

我在perlfaq8和他们的论坛中经历了解决方案,但他们不适合我。奇怪的是我不需要在任何情况下得到sdterr的输出,只要退出代码是正确的。

我使用Perl版本5.8.8,在Red Hat Linux 5

这里有一个例子我尝试:

my $cmd="less"; 
my $out=`$cmd 2>&1`; 

my $out=qx($cmd 2>&1); 

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

当指挥官d运行成功,我可以捕获stdout。

我不想使用额外的捕获模块。如何捕获外部命令的完整结果?

+0

只需使用[IPC ::运行](https://metacpan.org/module/IPC::Run )这使得这很容易。 – 2012-01-04 20:11:52

+0

相关:http://stackoverflow.com/q/3263912/2157640 – Palec 2014-09-12 15:23:12

回答

4

其实,写这个正确的方法是:

#!/usr/bin/perl 
$cmd = 'lsss'; 
my $out=qx($cmd 2>&1); 
my $r_c=$?; 
print "output was $out\n"; 
print "return code = ", $r_c, "\n"; 

你会得到一个“0”,如果没有错误,“-1”,如果错误。

4

STDERR旨在用于可能需要从STDOUT输出流中分离出的错误或消息。因此,我不会指望像less这样的命令输出中的任何STDERR

如果你想同时(或两者)流和返回代码,你可以这样做:

my $out=qx($cmd 2>&1); 
my $r_c=$? 
print "output was $out\n"; 
print "return code = ", $r_c == -1 ? $r_c : $r_c>>8, "\n"; 

如果该命令不是可执行文件(也许是因为你想用less但写道lsss代替)返回码将是-1。否则,正确的出口值是高8位。见system

8

这正是David Golden在写Capture::Tiny时遇到的挑战。我认为这会帮助你做到你需要的东西。

基本例如:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Capture::Tiny 'capture'; 

my ($stdout, $stderr, $return) = capture { 
    system('echo Hello'); 
}; 

print "STDOUT: $stdout\n"; 
print "STDERR: $stderr\n"; 
print "Return: $return\n"; 

几遍之后,你可能真的想capture_merged加入STDOUT和STDERR到一个变量,但我给的例子是好的,一般的,所以我会离开它。

1

这个问题经常给出的答案是使用包含shell类型重定向的命令行。然而,假设你想避免这种情况,并且使用open()和命令和参数列表,所以你不必太担心shell如何解释输入(可能部分由用户提供的值组成)。然后,而不是诉诸软件包,如IPC :: Open3,下面将读取标准输出和标准错误:

my ($child_pid, $child_rc); 

unless ($child_pid = open(OUTPUT, '-|')) { 
    open(STDERR, ">&STDOUT"); 
    exec('program', 'with', 'arguments'); 
    die "ERROR: Could not execute program: $!"; 
} 
waitpid($child_pid, 0); 
$child_rc = $? >> 8; 

while (<OUTPUT>) { 
    # Do something with it 
} 
close(OUTPUT); 
+0

这是此主题中的最佳答案。使用更多的代码,它会阻止使用shell重定向,它通常是bash。如果你详细评论它,这个例子会更好。但它在perldoc打开函数中有详细描述。 – Znik 2017-02-21 15:00:49

+0

有一个重要的问题,为什么你首先等待子进程并检查RC,然后读取其输出?我thik它应该交换。我认为这只是它正常工作的一个原因,它是由操作系统进行的管道缓冲。我认为如果外部“程序”会在stdout或stderr上产生大流,因为流重定向会挂起。 – Znik 2017-02-22 08:13:39

相关问题