根据时间在 perl 脚本中运行子程序?

2024-03-22

我有一个 perl 脚本,它作为守护进程一直循环运行。我想在基于时间(或计时器)的 perl 脚本中运行一个子函数,因此每 2 小时它将运行该子函数并继续其循环。我正在考虑获取纪元时间,然后通过循环检查几次,一旦它大于 2 小时,它就会运行子函数。在 perl 中是否有更好的方法来做到这一点?

Thanks,
LF4


这取决于自上次子例程启动开始或自上次执行结束以来是否应该有 2 小时。


1)如果是后者(运行最后一个子例程结束和新子例程开始之间有2小时),塞斯皮诺扎的解决方案是完全可以接受的(无限循环,并调用sleep(7200);执行子程序后)。

my $timeout = 7200;
while (1) {
    dostuff();
    sleep($timeout);
};

唯一的问题是它无法处理以下情况dostuff()需要永远,例如陷入困境 - 有关为什么这是需要考虑的重要情况以及解决方法的讨论,请参阅下文。


2) If the former (2 hours between starting points), you have three options, related to handling the subroutine run-time that exceeds 2 hours[0]. Your 3 options, explained in detail below, are to either:

2a) 启动一个新的子程序,同时旧的子程序继续运行(并行);

2b) 在旧子程序完成后启动新子程序;

2c) 启动一个新的子例程,但首先停止前一个子例程的执行。

2a 和 2c 选项要求您设置alarm() http://perldoc.perl.org/functions/alarm.html2 小时,并且触发警报时发生的情况有所不同。

[0]注意:由于任何子例程都可能至少需要 PC 的一些资源,因此总有可能(无论多么小)超过 2 小时,因此您必须选择这 3 个选项之一来处理这种情况。


2a) 每 2 小时启动一次,如果未完成,则与旧执行并行运行。

这个选项本质上是实现cron功能。

任何时候你听到“并行”这个词,你都可能会放弃这个过程。

my $timeout = 7200;
while (1) { # Not tested!
    eval {
        local $SIG{ALRM} = sub { die "alarm\n" };
        if (!defined($child_pid = fork())) {
            die "cannot fork: $!\n";
        } elsif (!$child_pid) { # Child
            dostuff();
            exit;
        } # Parent continues to sleep for 2 hours
        alarm $timeout; # You need it in case forking off take >2hrs
        sleep; # forever
    };
    die unless $@ eq "alarm\n"; # propagate unexpected errors
    # We don't need to check if $@ is true due to forever sleep
}

2b) 每2小时启动一次,如果旧的没有完成,让它运行直到完成

这可以重新表述为“启动任务,如果完成时间快于 2 小时,则睡眠剩余时间”

my $timeout = 7200;
while (1) {
    my $start = time;
    dostuff();
    my $end = time;
    my $lasted = $end - $start;
    if ($lasted < $timeout) {  
        sleep($timeout - $lasted);
    }
};

2c) 每两个小时开始一次,如果前一个没有完成,则超时并杀死它

每当你看到这样的逻辑时,答案显然就是警报。

while (1) {
    my $finished = 0;
    eval {
        local $SIG{ALRM} = sub { die "alarm\n" };
        alarm 7200;
        dostuff();
        $finished = 1;
        sleep; # forever
    };
    die unless $@ eq "alarm\n"; # propagate unexpected errors
    warn "Timed out!!!\n" unless $finished
}

附:正如 cespinoza 所指出的,您需要以某种方式对脚本进行守护进程(确保当您退出启动它的 shell 时它不会被杀死),通过 Unix 方式(例如以 nohup 启动它)或 Perlish 方式(在 on 上搜索 daemonize + Perl) Stackoverflow 的机制)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

根据时间在 perl 脚本中运行子程序? 的相关文章

随机推荐