首页 文章

Cron表达式每N分钟运行一次

提问于
浏览
3

我需要构建一个cron表达式,以便在用户单击开始按钮后每10分钟运行一次作业 .

我正在尝试做类似的事情:

0 42/10 * * * ? *

42/10就像用户点击开始hh:42(例如:18h42) . 下一个时间表如下:

1.  Friday, March 20, 2015 6:42 PM
2.  Friday, March 20, 2015 6:52 PM
3.  Friday, March 20, 2015 7:42 PM
4.  Friday, March 20, 2015 7:52 PM
5.  Friday, March 20, 2015 8:42 PM

问题是在第二次执行之后,作业等待一个小时来执行下一次执行 . 我如何构建一个立即启动并在N分钟后仍然运行的cron表达式?

预先感谢 .

3 回答

  • 0

    我认为你的格式错了 . 字段的顺序是:

    • 分钟

    • 小时

    • 几个月的日子

    • 星期几

    • 命令

    因此,在您的示例中, Minute 为0,并且 Hour 无效( Hour 必须在 0-23 范围内) . 我猜cron忽略了错误的 Hour ,并且每小时运行 Minute 0 .

    但是,如果您确实希望每N分钟运行一次,则可以使用类似的格式(其中N小于60):

    0/N * * * * /bin/echo "Your Command Here"
    

    但是,请记住 /N 在当前小时内每N分钟重复一次命令 . 所以,如果你的crontab中有 0/33 ,你的命令将在以下位置运行:

    • 00:00

    • 00:33

    • 01:00

    • 01:33

    不在:

    • 00:00

    • 00:33

    • 01:06

    • 01:39

  • 3

    如果你想每隔_2665302分钟运行一次cron,有三种情况需要考虑:

    • n 分钟(60可以被_2665304整除)

    • 每分钟 n 分钟 YYYY-MM-DD HH:MM:00 (通用)

    这是两个完全不同的情况,因为一个月内的天数 .

    后一种情况涵盖了60不能被_2665307整除的情况,并且通过简单的数学计算,您很快就会发现需要一个起点 .

    每隔n分钟(60可以被n整除)

    为此,我们使用定义范围和步长值的组合:

    man 5 crontab:步长值可以与范围结合使用 . 在带有/ <number>的范围之后指定在该范围内跳过数字值的跳过 . 例如,可以在'hours'字段中使用0-23 / 2来指定每隔一小时的命令执行(V7标准中的替代方案是0,2,4,6,8,10,12,14,16) ,18,20,22) . 星号后也允许步长值,因此如果指定要每两小时运行一次的作业,则可以使用* / 2 .

    请参阅以下示例:

    # Example of job definition:
    # .----------------- minute (0 - 59)
    # |   .------------- hour (0 - 23)
    # |   |  .---------- day of month (1 - 31)
    # |   |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
    # |   |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
    # |   |  |  |  |
    # *   *  *  *  *   command to be executed
      m/n *  *  *  *   command1
    

    这里, command1 将从m到59每隔n分钟执行一次 .

    这意味着 :

    • 如果 m<=n ,它们将始终间隔 n 分钟 . 例如 . m=2,n=10 ::这项工作将在几分钟内运行 2,12,22,32,42,52

    • 如果 m>n ,它们将始终间隔 n 分钟,除非在小时开始时 . 例如 . m=12,n=10 ::工作将在几分钟 12,22,32,42,52 运行 . 所以这里我们在 5212th 分钟之间跳了20分钟 .

    note: 你清楚地看到,如果 n 没有完美地划分60,你就会遇到问题 . 例如 . m=0,n=110,11,22,33,44,55 上运行,所以我们只有5分钟到下一次运行 .

    从分钟YYYY-MM-DD HH开始每隔n分钟:MM:00

    这个案例是通用的,涵盖60的不可分割性 .

    这里变得更有趣,需要采用不同的方法 . 当您拥有特定日期的连续计数器时,可以解决此问题 . 输入UNIX时间戳,自 1970-01-01 00:00:00 UTC 以来的总秒数 . 假设我们想要从McFly抵达Riverdale的那一刻开始:

    % date -d '2015-10-21 07:28:00' +%s 
    1445412480
    

    对于在2015-10-21 07:28:00之后每隔_2665326分钟运行一次cronjob,crontab将如下所示:

    # Example of job definition:
    # .---------------- minute (0 - 59)
    # |  .------------- hour (0 - 23)
    # |  |  .---------- day of month (1 - 31)
    # |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
    # |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
    # |  |  |  |  |
    # *  *  *  *  *   command to be executed
      *  *  *  *  *   mintestcmd "2015-10-21 07:28:00" 7 && command2
    

    mintestcmd 定义为

    #!/usr/bin/env bash
    starttime=$(date -d "$1" "+%s")
    # return UTC time
    now=$(date "+%s")
    # get the amount of minutes
    delta=$(( (now - starttime) / 60 ))
    # set the modulo
    modulo=$2
    # do the test
    (( delta % modulo == 0))
    

    Remark: UNIX时间以UTC格式给出 . 如果您的cron运行在受夏令时影响的不同时区,建议不要在2到3点之间运行命令 . 这可以跳过命令或运行命令两次(取决于时间是向前还是向后跳跃)

    Remark: UNIX时间不受闰秒的影响

    Remark: cron 没有亚秒精度

  • 1

    您无法根据用户输入或触发器创建cron表达式 .

    更好的解决方案是使用布尔标志来启用或禁用cron,即在用户启动触发器时启用cron服务方法,如下所示:

    public static boolean cronEnabled = false;
    
    public cronServiceMethod(){
      if(cronEnabled){
         // Keep your logic here
      }
    }
    
    // Call this method when user clicks the Start button
    public enableCron(){
      cronEnabled = true;
    }
    
    public disableCron(){
      cronEnabled = false;
    }
    

    就cron而言,让它每10分钟运行一次,如下所示:

    0 0/10 * * * ?
    

相关问题