I'm trying to test the Perl module IPC::Run3 but having difficulty in checking whether a command is failed or successful.
I know that IPC::Run3 issues an exit code if something is wrong with its arguments, but what about if the arguments are ok but the command does not exist? How can I test the following example?
Having a subroutine to call Run3
sub runRun3 {
my $cmd = shift;
my ($stdout, $stderr);
run3($cmd, \undef, \$stdout, \$stderr);
# if( $? == -1 ) {
if (! $stdout and ! $stderr) {
die "Something is wrong";
} else {
print "OK \n";
}
}
when command $cmds[0]
below is executed (the ls
command of *nix systems) it prints OK
as expected, but with command $cmds[1]
it just says No such file or directory at ./testrun3.pl line 18
.
With a test to the exit code I want it to print Something is wrong
instead.
#!/usr/bin/perl
use warnings;
use strict;
use IPC::Run3;
my @cmds = qw(ls silly);
runRun3($cmds[0]);
runRun3($cmds[1]);
Or what would be the best alternative to IPC::Run3 in cases like this? This is just an oversimplification of the process, but eventually I would like to capture STDERR and STDOUT for more complex situations.
Thanks.
A few points to go through.
First, for the direct question, the IPC::Run3 documentation tells us that
The error you ask about is of that kind and you need to eval the call to catch that exception
You can now print your own messages inside
if ($@) { }
block, when errors happen where the underlying system fails to execute. Such as when a non-existing program is called.Here
$@
relates toeval
while$?
tosystem
. So ifrun3
didn't have a problem and$@
is false next we check the status ofsystem
itself, thus$?
. From docsFor variables
$@
and$?
see General Variables in perlvar, andsystem
andeval
pages.A minimal version of this is to drop
eval
(and$@
check) and expect the program todie
ifrun3
had problems, what should be rare, and to check (and print) the value of$?
.A note on
run3
interface. With\@cmd
it expects@cmd
to contain a command broken into words, the first element being the program and the rest arguments. There is a difference between writing a command in a string, supported by$cmd
interface, and in an array. See system for explanation.Which alternative would suit you best depends on your exact needs. Here are some options. Perhaps first try IPC::System::Simple (but no
STDERR
on the platter). For cleanly capturing all kinds of output Capture::Tiny is great. On the other end there is IPC::Run for far more power.