Capture stdout/stderr and exit code in perl

The modern recommended way:

use strict;
use warnings;

use Capture::Tiny qw/capture/;

my $cmd = "ls -l /tmp /non_existant_path";
my ($stdout, $stderr, $exitcode) = capture {
    system( $cmd );
};
$exitcode >>= 8;

print "STDOUT:\n", $stdout, "\n";
print "STDERR:\n", $stderr, "\n";
print "Exit code: $exitcode\n";

If Capture::Tiny is not available, IPC::Open3 might be ( but this has some caveats ).

use strict;
use warnings;

use IPC::Open3;

local(*MY_STDIN, *MY_STDOUT, *MY_STDERR);

my $cmd = "ls -l /tmp /nonexistant_path";

my $childpid = open3(*MY_STDIN, *MY_STDOUT, *MY_STDERR, $cmd);
my @outlines = <MY_STDOUT>;
my @errlines = <MY_STDERR>;  # XXX: block potential if massive
close MY_STDOUT;
close MY_STDERR;

print "STDOUT:\n", @outlines, "\n";
print "STDERR:\n", @errlines, "\n";
waitpid($childpid, 0);
my $exitcode = $? >> 8;
print "Exit code $exitcode\n";

Using open3 may fail if the output being thrown in stdout/stderr is too large and cannot be buffered. This can be made to work with IO::Select. See also http://docstore.mik.ua/orelly/perl2/prog/ch32_31.htm .

Capture stdout/stderr and exit code in perl

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s