太长了;博士: 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 小时运行一次。
- 那么隐含着什么真的每两天一次?
这个答案声明 的 cronjob
0 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;