【问题标题】:How to simulate a cron job如何模拟 cron 作业
【发布时间】:2011-04-01 18:53:18
【问题描述】:

我想每天运行一次脚本(仅在周末),但是我不能为此使用 cron 作业。

我在想有一个无限的while循环,睡24小时,检查是否是周末,如果是则执行脚本。

linux下bash下有什么好的解决办法?

我目前的实现:

#! /bin/bash

 while [ true ]; do
    if [[ $(date +%u) -lt 6 ]]; then
               ./program
        else
             echo Today is a weekend, processing is skipped. Back to sleep.
    fi
    sleep  86400
done

我将在下午 5 点启动此脚本。

【问题讨论】:

  • cron 是一个很好的解决方案。你能告诉我们为什么你不能使用它吗?
  • 您能详细说明您的限制条件吗? “在”工作可能是不可接受的?服务器重启后作业是否应该自动重启?
  • 我没有使用 cron 表的权限。让我们假设服务器不会重新启动。
  • 您是否有权使用atbatch
  • 您对这些事件的时间安排有多准确?是否必须在当天下午 5:00 发生,还是在下午 5 点到 6 点之间的某个时间可以接受准确度?

标签: perl bash scripting cron


【解决方案1】:

使用长 sleep 的问题在于,您的程序对时间的概念会漂移。最好只循环短 sleep 句点并检查您是否在所需的窗口内。

如果您的管理员不允许您使用 cron,他们可能不会因为您绕过该限制而感到高兴。

但是,这里有一个粗略的大纲:

while :
do
    dow=$(date +%u)
    if (( dow == 6 || dow == 7 ))
    # you can check a flag or counter to limit the number of times it's performed
    # or use a more refined date spec than just whole days (times of day, in other words)
    then
        do_something
        sleep 1h    # or use a smaller or larger interval
    fi
done

【讨论】:

  • 您在周末每天至少执行 24 次 do_something。固定的 24 小时睡眠是行不通的,因为睡眠可以提早恢复。
  • 这几乎就是我想出的。我将在原始问题中发布它
【解决方案2】:

假设您真的不能使用 cron 或 at 来安排作业,您将需要编写一个睡眠循环。您如何编写它的详细信息将根据您的要求而有所不同。

如果您只想每天执行一次,则必须担心睡眠时间短。大多数语言 sleep 函数下的 sleep 系统调用并不能保证它会休眠请求的时间长度。您的程序可能会比请求的睡眠时间稍长或比请求的睡眠时间短得多。您可以安排 24 小时睡眠,但操作系统可能会在几个小时甚至几秒钟后唤醒您的程序以发送信号。如果您没有跟踪上次运行,或者您的下一次预期运行,您可以每天执行多次。

如果您想在特定时间执行,则需要改变睡眠时间。部分睡眠可能会让你昏迷半天,你需要睡 12 小时才能恢复同步。

您需要考虑夏令时/夏令时。一年一天有 23 小时,另一天有 25 小时。

您可以使用类似于此伪代码的内容:

set next_time_to_run
loop forever
    sleep time_difference_in_seconds(current_time, next_time_to_run)
    if current_time is close to next_time_to_run
        execute code
        update next_time_to_run
    end if
end loop

【讨论】:

    【解决方案3】:

    对于 Perl 解决方案,请查看 Schedule::Cron CPAN 模块:

    use 5.012;
    use warnings;
    use Schedule::Cron;
    
    my $cron = Schedule::Cron->new( sub {} );
    
    # add weekend run @ 05:00 
    $cron->add_entry('0 5 * * Sat,Sun', sub {
        system './program';
    });
    
    $cron->run();
    

    【讨论】:

      【解决方案4】:

      您可以使用snaked。它类似于 cron,但用 Perl 编写。

      【讨论】:

        【解决方案5】:

        在没有每个用户的 crontab 的那一天,我经常使用 at(1) 来完成此操作。

        #!/bin/sh
        ... do stuff...
        at -f /path/to/me 5pm tomorrow
        

        这样,您的脚本就会运行并自行安排下一次调用。

        我认为您不能指定“下周末”的时间规格,因此如果不是周末,您只需每天重新安排并让脚本退出(安排下一个工作后)。

        编辑:或者不是每天安排,而是找出今天是什么并适当安排。例如

        day=Saturday
        if [ $(date +%u) -eq 6 ] ; then day=Sunday ; fi
        at -f /path/to/me 5pm next $day
        

        如果此脚本在周六运行,它会安排下周日运行下一次,否则下周六运行。 [ $(date +%A) = Saturday ] 可能更具可读性,但 %A 将提供特定于语言环境的字符串,因此如果您更改语言环境可能无法正常工作。

        【讨论】:

          猜你喜欢
          • 2010-10-25
          • 1970-01-01
          • 2011-06-16
          • 2011-08-15
          • 2020-06-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多