Updated: November 9, 2016
The following is a cross-platform demonstration for capturing STDERR.
use strict;
use warnings;
use File::Temp qw/ tempfile /;
# Initially, borrowed bits from IPC::Run3 for capturing STDERR.
# Then, made efficient for lesser overhead than Capture::Tiny.
sub do_cmd {
my ( $cmd ) = @_;
my ( undef, $err_file ) = tempfile();
my ( $err, $err_fh, @result ) = ('');
if ( $^O eq 'MSWin32' ) {
# this is one way to capture STDERR, also works on Unix
open my $cmd_fh, "$cmd 2> $err_file |" or die "$!\n";
@result = <$cmd_fh> if defined ( fileno $cmd_fh );
close $cmd_fh;
}
else {
# this is another way, but not supported on Windows
local *STDERR_SAVE;
open STDERR_SAVE, '>&STDERR';
open $err_fh, '+>', $err_file;
binmode $err_fh, ':raw';
open STDERR, '>&' . fileno $err_fh;
open my $cmd_fh, "$cmd |" or die "$!\n";
@result = <$cmd_fh> if defined ( fileno $cmd_fh );
close $cmd_fh;
open STDERR, '>&STDERR_SAVE';
close $err_fh;
}
if ( -s $err_file ) {
open $err_fh, '<', $err_file;
local $/ = undef; $err = <$err_fh>;
close $err_fh;
}
unlink $err_file;
return ( $err, @result );
}
# Demonstration.
my $pass = 'password';
my $ip = 'ip_address';
my $cmd = 'uptime';
my ($err, @result) = do_cmd("sshpass -p $pass ssh user\@$ip $cmd");
if (length $err) {
print "ERROR: $err\n";
} else {
chomp @result;
}
|