Reputation: 1813
I would like to run a separate process in Perl (a command line PHP script). I would like to capture this processes output AND return code. Optionally I would like to be able to terminate the process and move on if the process takes longer than N seconds. What should I look into?
Upvotes: 0
Views: 833
Reputation: 2274
Without considering the optional part of your question, you can obtain the output of a command within backticks, and its return value in the special variable $?
.
my $output = `shell_command`;
die ("shell_command failed!\n") if ($?);
Upvotes: 0
Reputation: 1361
This is a frequently asked question. Have a look at this Perl FAQ too. It basically explains the way to run external commands in Perl.
Upvotes: 1
Reputation: 22254
Personally, I find the easiest is AnyEvent with AnyEvent::Util::run_cmd and a timer. There is no requirement here to run your entire program under an event loop, I regularly go in and out of the event loops with this solution today. (The following isn't warnings-safe.)
use AnyEvent;
use AnyEvent::Util;
my ($stdout, $stderr, $pid);
my $cv = AnyEvent::Util::run_cmd [ $^X, -e => '$|++; sleep 2; print "foo\n"; sleep 2' ],
'>' => \$stdout,
'2>' => \$stderr,
'$$' => \$pid,
;
my $w = AnyEvent->timer(after => 3, interval => 0, cb => sub { print "killing!\n"; kill SIGINT => $pid });
my $rc = $cv->recv();
$w = undef; # end the timer.
print "got rc = [$rc]\n";
print "stdout = [$stdout]\n";
print "stderr = [$stderr]\n";
Upvotes: 2
Reputation: 7357
You can use piped open() to get all 3 goals:
my $pid = open(F, "cat /etc/passwd |") || die "Cant open pipe: $!";
eval {
# Give 30 secs to read output:
local $SIG{ALRM} = sub { kill(9, $pid); die "alarm\n"; }; # NB: \n required
alarm(30);
# Read output:
my $line = <F>;
alarm(0); # Remove alarm
#..do job with $line
};
# Get errorcode:
close(F);
print "Exit status: $?\n";
printf "Exit value(return code): %d\n", $?>>8;
print "Killed by timeout\n" if ($? & 127)==9;
Upvotes: 1
Reputation: 98398
use IPC::System::Simple qw/EXIT_ANY $EXITVAL capture/;
my $output = capture(EXIT_ANY, 'some command');
print "exit value was $EXITVAL\n";
EXIT_ANY
tells capture to allow any exit value; you can instead list allowed ones (capture([0,1,42], ...)
) and capture will throw an exception if another is encountered. By default (if just a command is passed to capture) any non-zero exit value results in an exception.
Upvotes: 1