Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
根据时间在perl脚本中运行sub?_Perl - Fatal编程技术网

根据时间在perl脚本中运行sub?

根据时间在perl脚本中运行sub?,perl,Perl,我有一个perl脚本,它一直作为守护进程循环运行。我想在基于时间(或计时器)的perl脚本中运行一个子函数,这样每2小时它就会运行该子函数并继续其循环。我想得到epoch时间,然后通过循环检查几次,一旦超过2小时,它就会运行子函数。在perl中有更好的方法吗 谢谢, LF4像crontab这样的东西最适合做这样的定时工作。但是,如果要运行Perl守护进程,则必须使用某种事件处理程序。我脑子里有两个选择,一个是和。这取决于自上次子例程启动开始还是自上次执行结束后应该有2个小时 1) 如果是后者(

我有一个perl脚本,它一直作为守护进程循环运行。我想在基于时间(或计时器)的perl脚本中运行一个子函数,这样每2小时它就会运行该子函数并继续其循环。我想得到epoch时间,然后通过循环检查几次,一旦超过2小时,它就会运行子函数。在perl中有更好的方法吗

谢谢,

LF4

像crontab这样的东西最适合做这样的定时工作。但是,如果要运行Perl守护进程,则必须使用某种事件处理程序。我脑子里有两个选择,一个是和。

这取决于自上次子例程启动开始还是自上次执行结束后应该有2个小时


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

<> P>唯一的问题是,它不能处理“代码> doSuffor”永远的问题,例如陷入困境,讨论为什么要考虑的重要情况和解决方法,见下文。
2) 如果是前者(起点之间间隔2小时),则有三个选项与处理超过2小时的子程序运行时间相关[0]。下面详细介绍了您的3个选项:

2a)在旧子程序保持运行(并行)的同时启动新子程序

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

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

2a和2c选项要求您将报警设置为2小时,并且在触发报警时发生的情况不同

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


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

该选项本质上是实现
cron
功能

每当你听到parallel这个词,你很可能会放弃这个过程

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



另外,正如cespinoza所指出的,您需要以某种方式对脚本进行后台监控(确保在退出启动脚本的shell时脚本不会被杀死),方法可以是Unix方式(例如以nohup方式启动脚本)或Perlish方式(在Stackoverflow上搜索daemonize+Perl以了解其机制)。

您可能需要检查任务规划和执行情况

有没有理由不将该功能移动到单独的脚本并从cron调用它?该脚本在登录后使用IMAP检查电子邮件,并以给定的速率检查新邮件,从不注销。我遇到了一个问题,它将被挂起,我想这是因为会话将过期。我想将脚本设置为在给定的时间范围内注销和登录,这样它就不会挂起,但不会中断检查循环。另一种方法是检查每个IMAP事务后生成的任何错误,看看它们是否指示连接已断开。如果是这样,请重新初始化连接并重新发出事务。这是一个经过深思熟虑的答案,但根据我对问题的理解,这似乎会在睡眠时阻塞主执行循环。因此,它只能每2小时dostuff()一次。我的理解是,它在一个连续循环中调用dostuff(),可能每小时调用100次,然后每隔2小时就需要执行_subfunction()。@ben-这很容易合并到所有3个“2abc”解决方案中。在循环中使用“每N分钟一次呼叫”预先结束“睡眠”;在基于警报的解决方案的评估中。感谢DVK提供的非常周到的答案,该脚本每隔15秒检查收件箱中的任何新消息,并设置为守护进程。使用这样的偶数处理程序,您可以拥有多个计时器。因此,如果你想每5分钟做一次dostuff(),每2小时做一次其他事情(),事件处理程序可以帮你解决这个问题。你可以通过检查epoch time来自己做,但是有相当多的复杂性(如果在你跑步时时间发生了变化怎么办?),你将重新发明轮子。
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
}
my $timeout = 7200;
while (1) {
    my $start = time;
    dostuff();
    my $end = time;
    my $lasted = $end - $start;
    if ($lasted < $timeout) {  
        sleep($timeout - $lasted);
    }
};
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
}