10

假设我想从我的脚本中运行一个带有反引号的外部程序,同时我想同时捕获 STDOUT 和 STDERR,但使用两个不同的变量。我怎样才能做到这一点?例如,如果我运行这个脚本......

my $cmd = `snmpwalk -v $version -c $community $hostname $oid`;

...如果没有错误,一切正常,但如果命令引发错误,则此错误将打印在命令行上,我不希望这种情况发生。我也想捕获错误。无需在屏幕上打印任何内容。有任何想法吗?

4

4 回答 4

13

您不必一直到open3,IIRC 仅适用于您需要读取和写入外部命令的情况,即使那样还有其他方法。

对于您的问题,我建议使用Capture::Tiny,它可以从其块内运行的任何东西中捕获(甚至是 tee)STDOUT 和 STDERR。例如,根据您的问题:

#!/usr/bin/env perl

use strict;
use warnings;

use Capture::Tiny qw/capture/;

...

my ($stdout, $stderr) = capture {
  system ( "snmpwalk -v $version -c $community $hostname $oid" );
};

对于另一个示例,请考虑以下功能代码:

#!/usr/bin/env perl

use strict;
use warnings;

use Capture::Tiny qw/capture/;

my ($stdout, $stderr) = capture {
  system ( "echo 'hello'" );
  system ( "date" );
  warn "Arg1!";
};

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

这只是给了我:

STDOUT:
hello
Mon Dec 19 23:59:06 CST 2011
STDERR:
Arg1! at ./test.pl line 11.
于 2011-12-20T06:00:30.087 回答
8

使用反引号执行此操作的唯一方法是重定向到 shell 命令内的文件:

   my $cmd = `snmpwalk -v $version -c $community $hostname $oid 2>error.dat`;

如果要在脚本中捕获 STDERR,则需要IPC::Open3而不是反引号

于 2011-12-05T11:35:06.600 回答
5

在 Perl 常见问题解答中,您有不同的选项,具体取决于您要如何进行:

http://perldoc.perl.org/perlfaq8.html#How-can-I-capture-STDERR-from-an-external-command%3f

于 2011-12-05T14:30:26.820 回答
0

IO::捕获输出

是您想要做的非常方便的包装器。

于 2011-12-05T19:40:34.077 回答