0

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?

2
  • Now it says "Perl" and your comments can be deleted. Commented Nov 26, 2012 at 21:11
  • Please don't revert the edit back to uppercase. :) It really is "perl" or "Perl", but not "PERL" Commented Nov 26, 2012 at 21:53

6 Answers 6

2

You can try IPC::Run.

IPC::Run - system() and background procs w/ piping, redirs, ptys (Unix, Win32)

Sign up to request clarification or add additional context in comments.

Comments

2

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";

Comments

1
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.

Comments

1

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;

Comments

1

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.

Comments

0

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 ($?);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.