I currently have a Perl script that runs an external command on the system, gathers the output, and performs some action based on what was returned. Right now, here is how I run this (where $cmd is a string with the command setup):
@output = `$cmd`;
I'd like to change this so if the command hangs and does not return a value after so much time then I kill the command. How would I go about running this asynchronously?
From Perl HowTo, the most common ways to execute external commands from Perl are: my $files = `ls -la` — captures the output of the command in $files. system "touch ~/foo" — if you don't want to capture the command's output. exec "vim ~/foo" — if you don't want to return to the script after executing the command.
Perl's system command provides a way to execute a shell command on the underlying platform. For example, if you are running on a Unix platform, the command: system("ls -l") will print a long listing of files to stdout.
There's a LOT of ways to do this:
If you really just need to put a timeout on a given system call that is a much simpler problem than asynchronous programming.
All you need is alarm() inside of an eval() block.
Here is a sample code block that puts these into a subroutine that you could drop into your code. The example calls sleep so isn't exciting for output, but does show you the timeout functionality you were interested in. Output of running it is:
/bin/sleep 2 failure: timeout at ./time-out line 15.
$ cat time-out
#!/usr/bin/perl
use warnings;
use strict;
my $timeout = 1;
my @cmd = qw(/bin/sleep 2);
my $response = timeout_command($timeout, @cmd);
print "$response\n" if (defined $response);
sub timeout_command {
my $timeout = (shift);
my @command = @_;
undef $@;
my $return = eval {
local($SIG{ALRM}) = sub {die "timeout";};
alarm($timeout);
my $response;
open(CMD, '-|', @command) || die "couldn't run @command: $!\n";
while(<CMD>) {
$response .= $_;
}
close(CMD) || die "Couldn't close execution of @command: $!\n";
$response;
};
alarm(0);
if ($@) {
warn "@cmd failure: $@\n";
}
return $return;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With