These methods each have different ways of indicating success, and there are also two different kinds of success: whether it successfully executes, and the exit status returned by the process.
IPC::System::Simple system
will throw an exception if the command fails or returns a non-zero status. You can define acceptable non-zero statuses by passing an arrayref as the first argument. It is easiest when you want to allow errors to cause your program to die with a useful error message, so you don't need any exception handling like eval or try/catch.
use strict;
use warnings;
use IPC::System::Simple qw(system EXIT_ANY);
system $cmd; # failure or non-zero exit will cause program to die
my $exit = system EXIT_ANY, $cmd; # failure to execute will cause program to die
use Syntax::Keyword::Try;
try {
system $cmd;
} catch {
# error in $@
}
try {
my $exit = system [0..5], $cmd;
if ($exit) {
# one of the allowed non-zero exit status
}
} catch {
# error in $@
}
try {
my $exit = system EXIT_ANY, $cmd;
if ($exit) {
# non-zero exit status
}
} catch {
# error starting command in $@
}
IPC::Run3 will throw an exception if the command fails, and set $? to the wait status. Its return value is always true.
use strict;
use warnings;
use IPC::Run3;
use Syntax::Keyword::Try;
try {
run3 $cmd;
if ($?) {
# non-zero exit status
my $exit = $? >> 8;
}
} catch {
# error starting command in $@
}
qx
or backticks which is the readpipe operator will not throw an exception, but will return undef if the command failed to start, and otherwise set $?
the same way as IPC::Run3.
use strict;
use warnings;
my $output = `$cmd`;
if (!defined $output) {
# error occured starting command, check $!
} elsif ($?) {
# non-zero exit status
my $exit = $? >> 8;
}
The built-in system function will return the wait status, or -1 if the command failed to start, and set the same value in $?
.
use strict;
use warnings;
system $cmd;
if ($? == -1) {
# error occured starting command, check $!
} elsif ($?) {
# non-zero exit status
my $exit = $? >> 8;
}
Note that all of these options aside from the readpipe operator (but see my IPC::ReadpipeX) support passing a command in list form, which bypasses the shell and thus safer when the command may contain arbitrary input, but sometimes can be buggy on Windows as it only pretends to bypass the shell there.
system 'pmcmd.exe', 'startworkflow', '-sv', ...;
run3 ['pmcmd.exe', ...];