从perl中的external * nix命令获取STDOUT,STDERR和响应代码

时间:2012-01-04 19:56:00

标签: perl stdout stderr

我想从我的Perl脚本中执行外部命令,将stdout和stderr的输出放入我选择的$variable中,并将命令的退出代码放入$?变量中

我在perlfaq8和他们的论坛中找到了解决方案,但他们并没有为我工作。奇怪的是,只要退出代码是正确的,我就不会获取sdterr的输出。

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

这是我正在尝试的一个例子:

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

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

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

当命令成功运行时,我可以捕获stdout。

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

4 个答案:

答案 0 :(得分:9)

这正是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 :(得分:5)

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

#!/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'。

答案 2 :(得分:4)

STDERR旨在用于可能需要与STDOUT输出流分离的错误或消息。因此,我不希望STDERR等命令的输出中有任何less

如果你想要两个(或者任何一个)流和返回代码,你可以这样做:

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

答案 3 :(得分:1)

这个问题经常给出的答案是使用包含shell类型重定向的命令行。但是,假设您要避免这种情况,并将open()与命令和参数列表一起使用,因此您不必担心shell如何解释输入(可能部分由用户提供的值组成)。然后不使用IPC :: Open3等软件包,以下内容将同时读取stdout和stderr:

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);