间隔 cron 何时第一次执行? (例如:*/3 天)

间隔 cron 何时第一次执行? (例如:*/3 天)

太长了;博士: cron 是否使用间隔的数值与当天的数值进行比较来确定其执行时间,还是字面上的“每 3 天”在创建后的规定时间执行?

问题:

如果我添加以下作业,crontab -e它会在明天午夜第一次运行还是从明天开始三天运行?或者仅在该月的“第三”天?第 1 天、第 4 天、第 7 天、第 10 天……?

0 0 */3 * * /home/user/script.sh

我昨天把这个 cron 放进去,今天早上它运行了(这可能是我问题的答案),但我想验证这是正确的。今天是 31 号,该间隔值似乎确实属于该序列。如果 cron 在本月 1 日开始执行一个间隔,它明天会再次运行吗?

补充笔记:

已经有一些关于 cron 的优秀帖子和资源一般来说(这是我知道的一个常见话题),但是特定间隔的起点对我来说并不那么清楚。多个来源以多种方式表述它:

  • unixgeeks.org帖子指出:

    Cron 还支持“步骤”值。 dom 字段中的值 */2 表示该命令每两天运行一次,同样,hours 字段中的 */5 表示该命令每 5 小时运行一次。

    • 那么隐含着什么真的每两天一次?
  • 这个答案声明 的 cronjob0 0 */2 * *将“在每个奇数日的 00:00 执行(步骤 2 的默认范围,即 1,3,5,7,...,31)”

    • cron 总是从该月的第一天开始吗?
    • 该博客似乎指出 cron 将在 31 日执行,然后在下个月 1 日再次执行(因此连续两天),因为间隔基于当天的数值。
  • 另一个例子从这篇博文

    • 0 1 1 */2 * command to be executed应该每两个月的第一天凌晨 1 点执行
    • 这是否意味着 cron 将执行第 1、3、5、7、9、11 个月?

看来 cron 的设计目的是*/3根据间隔的数值与日(或秒、分、小时、月)的数值进行比较来执行间隔 cronjobs ( )。这是100%正确的吗?

聚苯乙烯这是一个关于 cron 的一个特定功能的非常具体的问题,(我认为)需要一些澄清。这应该可以让 Google 100% 确定地告诉您,您的“每 3 个月”的 cron 在添加到 crontab 后将首次运行。

答案1

crontab(5) 手册页使用非常清楚的措辞:

步长值可以与范围结合使用。范围后面带有“/number”指定在该范围内跳过数字值。例如,可以在小时字段中使用“0-23/2”来指定每隔一小时执行一次命令(V7 标准中的替代方法是“0,2,4,6,8,10,12,14,16 ,18,20,22")。星号后也允许使用步骤,因此如果您想说“每两个小时”,只需使用“*/2”。

确切的措辞(和示例)是“在范围内跳过数字值” - 这意味着它从范围中的第一个数字开始。

这意味着如果范围是天,则在or1-31的情况下返回的值是 1,3,5,7.. 等。这也意味着范围在运行完后将重置为起始值。1-31/2*/2

所以你也是正确的,在这种情况下,cronjob 将在下个月的 31 日和 1 日运行。

请注意,cron 有 2 个互斥的字段 - “月份中的某一天”和“星期几”。因此,当运行间隔天的作业时,您必须选择其中之一。

如果您想定义一个每隔一天完美运行的 cronjob,则必须使用多行并根据当前日历自定义每个月。

答案2

今天(2020-07-31)是问这个问题的最佳日子,因为 30 有很多因素。

我的理解(根据记忆)是(a) * 扩展到范围 1-31,然后(b) /3 是该列表的跳过增量。因此,如果您写为 3-31/3,它将在 3 日、6 日、9 日、..、27 日(2 月)或 30 日(其他月份)运行。 man -s 5 crontab 暗示了范围,但不包括从基值以外开始的示例。

我为每个跳过值设置了一个 crontab (Linux Mint 18.1):

30 13 */1 * * date > /home/paul/cron.1.log
30 13 */2 * * date > /home/paul/cron.2.log
30 13 */3 * * date > /home/paul/cron.3.log
...
30 13 */30 * * date > /home/paul/cron.30.log
30 13 */31 * * date > /home/paul/cron.31.log

它仅在跳跃为 1、2、3、5、6、10、15 和 30 的地方运行。这看起来像 (31 - 1) 的所有因数。

然后我将每个范围更改为 7-31/,当跳跃为 1、2、3、4、6、8、12 和 24 时触发。这就是 (31 - 7) 的所有因数。

对于范围 8-31,仅跳过 1 和 23 射击,因为 (31 - 8) 是质数。

答案3

对于那些想在这里查看一些代码的人来说,这证实了其他答案中的结论。

cron.h定义不同类型(如 HOUR、MONTH、DAY)的第一个和最后一个可能元素。

#define FIRST_HOUR  0
#define LAST_HOUR   23
#define HOUR_COUNT  (LAST_HOUR - FIRST_HOUR + 1)

#define FIRST_DOM   1
#define LAST_DOM    31
#define DOM_COUNT   (LAST_DOM - FIRST_DOM + 1)

#define FIRST_MONTH 1
#define LAST_MONTH  12
#define MONTH_COUNT (LAST_MONTH - FIRST_MONTH + 1)

入口.c, '*' 使用这些限制解析为一个范围

if (ch == '*') {
    /* '*' means "first-last" but can still be modified by /step
     */
    num1 = low;
    num2 = high;

步长 (num3) 默认为 1,但如果 crontab 中存在,则可以覆盖

    ch = get_number(&num3, 0, PPC_NULL, ch, file);
    if (ch == EOF)
        return EOF;
} else {
    /* no step.  default==1.
     */
    num3 = 1;

然后使用给定的步长从第一个到最后一个迭代来创建所有有效元素。因此第一个元素始终是范围的开头。

/* range. set all elements from num1 to num2, stepping
 * by num3.  (the step is a downward-compatible extension
 * proposed conceptually by bob@acornrc, syntactically
 * designed then implmented by paul vixie).
 */
for (i = num1;  i <= num2;  i += num3)
    if (EOF == set_element(bits, low, high, i))
        return EOF;

相关内容