How to capture both STDOUT and STDERR in two diffe

2019-03-27 09:16发布

Let's say I want to run an external program from my script with backticks and at the same time I want to capture both STDOUT and STDERR but in two different variables. How can I do that? For istance if I run this script...

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

...if there is no error everything works just fine BUT if the command raise an error this error will be printed on the command line and I don't want that to happen. I want to capture the error as well. Nothing has to be printed on the screen. Any ideas?

4条回答
SAY GOODBYE
2楼-- · 2019-03-27 09:46

In the Perl FAQ you have different options depending how do you want to proceed:

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

查看更多
smile是对你的礼貌
3楼-- · 2019-03-27 09:46

IO::CaptureOutput

is a very convenient wrapper for what you want to do.

查看更多
何必那么认真
4楼-- · 2019-03-27 09:56

The only way to do this with backticks is to redirect to a file inside the shell command:

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

If you want to capture the STDERR inside your script, you need IPC::Open3 instead of backticks

查看更多
We Are One
5楼-- · 2019-03-27 10:00

You needn't go all the way to open3, which IIRC is only for when you need to read and write to an external command, and even then there are other methods.

For your problem I suggest using Capture::Tiny, which can capture (or even tee) the STDOUT and STDERR from anything run inside its block. For example, per your question:

#!/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" );
};

For another example consider this functioning code:

#!/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";

which just gave me:

STDOUT:
hello
Mon Dec 19 23:59:06 CST 2011
STDERR:
Arg1! at ./test.pl line 11.
查看更多
登录 后发表回答