在perl中实现看门狗

时间:2014-02-03 14:52:18

标签: multithreading perl shell process watchdog

我需要在固定的时间窗口中包含外部进程(命令行调用)的执行。

经过几次阅读后,我编写了这个实现:

#/bin/perl -w

use IPC::System::Simple qw( capture );

use strict;
use threads;
use threads::shared;
use warnings;

my $timeout = 4;
share($timeout);

my $stdout;
share($stdout);

my $can_proceed = 1;
share($can_proceed);

sub watchdogFork {
    my $time1 = time;

    my $ml = async {
        my $sleepTime = 2;
        my $thr = threads->self();
        $stdout = capture("sleep $sleepTime; echo \"Good morning\n\";");
        print "From ml: " . $stdout;
        $thr->detach();
    };

    my $time2;
    do {
        $time2 = time - $time1;
    } while ( $time2 < $timeout );
    print "\n";

    if ( $ml->is_running() ) {
        print "From watchdog: timeout!\n";
        $can_proceed = 0;
        $ml->detach();
    }
}
my $wd = threads->create('watchdogFork');
$wd->join();

print "From main: " . $stdout if ($can_proceed);

$timeout > $sleepTime返回时:

From ml: Good morning
From main: Good morning

另一方面,当$timeout < $sleepTime

From watchdog: timeout!

获得的行为是正确的,但我认为这种做法略显原始。

我想知道是否有库可以帮助改进源代码以提高可读性和性能。有什么建议吗?

2 个答案:

答案 0 :(得分:2)

IPC::Run可让您运行子流程并与其stdinstdoutstderr进行互动。您还可以设置timeouts,在超出时抛出异常:

use IPC::Run qw(harness run timeout);

my @cmd = qw(sleep 10); 
my $harness = harness \@cmd, \undef, \my $out, \my $err, timeout(3);

eval {
    run $harness or die "sleep: $?";
};
if ($@) {
    my $exception = $@; # Preserve $@ in case another exception occurs
    $harness->kill_kill;

    print $exception; # and continue with the rest of the program
}

请注意,有一些limitations when running on Windows

答案 1 :(得分:1)

您可以使用Proc::Background中的timeout_system

use Proc::Background qw(timeout_system);

my $wait_status = timeout_system($seconds, $command, $arg1, $arg2);
my $exit_code = $wait_status >> 8;

该过程将在$seconds秒后被杀死。