根据时间在 perl 脚本中运行 sub? [英] Run a sub in a perl script based on the time?

查看:108
本文介绍了根据时间在 perl 脚本中运行 sub?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a perl script that runs as a daemon looping all the time. I want to run a subfunction in a perl script that is based on the time (or timer) so every 2hrs it would run that subfunction and continue with it's loop. I'm thinking getting the epoch time and just checking it a few times through the loop and once it's greater then 2hrs it runs the subfunction. Is there a better way to do this in perl?

谢谢,
LF4

推荐答案

这取决于自上次启动子程序的 START 起还是自上次执行的 END 起应该有 2 小时.

This depends on whether there should be 2 hours since the START of the last subroutine launch, or since the END of last execution.

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

1) If the latter (2 hours between the end of running the last subroutine and the start of new one), cespinoza's solution is perfectly acceptable (loop infinitely, and call sleep(7200); after executing the subroutine).

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

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

The only problem with this is that it can't handle the case where dostuff() takes forever, e.g. gets stuck - for the discussion of why it's an important situation to consider and approaches to solve, see below.

2) 如果是前者(起点之间 2 小时),您有三个选项,与处理超过 2 小时的子程序运行时间有关[0].您的 3 个选项(详细说明如下)是:

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) 启动一个新的子程序,而旧的子程序继续运行(并行);

2a) kick off a new subroutine while the old one keeps running (in parallel);

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

2b) to kick off a new subroutine AFTER the old one finishes;

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

2c) to kick off a new subroutine but first stop the execution of the prior one.

2a 和 2c 选项要求您为 2 设置 alarm()小时,并在触发警报时发生的情况有所不同.

2a an 2c options require you to set an alarm() for 2 hours, and differ in what happens when an alarm gets triggered.

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

[0] NOTE: since any subroutine is likely to require at least SOME resources from the PC, there's always a - however small - chance that it would exceed 2 hours, so you have to pick one of those 3 options to handle such a scenario.

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

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

This option is, essentially, implementing cron functionality.

每当你听到平行这个词时,你很可能会放弃这个过程.

Anytime you hear the word parallel, you would likely fork off the process.

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 小时,则睡眠剩余时间"

This can be re-worded as "kick off task, if it finishes faster than 2 hours, sleep for the remainder"

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

<小时>

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

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

Whenever you see logic like this, alarm is obviously the answer.

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 方式(搜索 daemonize + Perl on其机制的 Stackoverflow).


P.S. As cespinoza noted, you need to somehow daemonize the script (ensure it doesn't get killed when you exit the shell that started it), by either Unix means (e.g. launching it as nohup) or Perlish means (search for daemonize + Perl on Stackoverflow for mechanics of that).

这篇关于根据时间在 perl 脚本中运行 sub?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆