这是一个着名的"问题",当crontab行包含星期和月中的某一天时,cron使用OR来计算一天来发出命令.例如,如果你写
* * 13 * 5 command
该命令将在每个星期五和每月的第13天执行,而不仅仅是在星期五的第13天.这与其他字段的格式相矛盾(当您编写30 2***时,它将仅在小时和分钟时执行 - 正是您指定的;除了DoW和DoM之外的所有其他字段都相同).
所以我的问题是:这个例外是否有特定的原因?我的意思是,应该有一个理由,但我似乎无法找到它.(相反,我看到互联网中的很多人都希望像其他任何一样对待这些领域 - 使用"AND策略",正好适用于"星期五13"或"5月的第2个星期四"之类的东西.)
回到Vixie cron之后,System V cron中出现了“ wday OR mday”逻辑,但System III或更早版本中没有。
在Paul Vixie编写cron替代人之前,BSD cron就像SysIII及更早的cron。所有5个字段都进行了AND运算。4.4版之后的BSD采用了Vixie cron,使自己更像SysV。
所以不要问(怪罪)Vixie。他只是在克隆SysV。
SysV为什么这样做?我不知道,但我会尝试提供一些线索...
为了尝试了解SysV中发生了什么,它有助于查看源(在-SysIII之前和在-SVr4 之后)以及新行为的文档:
注意:可以通过两个字段(月中的天和周中的天)来指定天数。如果将两者都指定为元素列表,则都遵守。
(摘录自SunOS 4.1.3手册页。这似乎是SysV-ish。BSDcron在Paul Vixie撰写他的替代书之前从未有过这种行为。)
“两者都遵守”是使用AND和OR的普通布尔表达式的令人困惑的替代。几十年后,它仍在OpenSolaris手册页中:
可以通过两个字段(星期几和星期几)来指定天数。如果指定为元素列表,则两者都遵守。
SysV代码是完整的重写。它的功能之一是长时间没有作业要运行时会长时间睡眠。(较早的cron每分钟都会醒来,并将当前时间与所有作业规范进行比较。)计算功能(next_time
)顶部的注释说明:NOTE: this routine is hard to understand.
确实很难理解。这是“查找此crontab行的下一次执行时间”功能,而不是“确定当前时间是否与此crontab行相匹配”功能,因此,即使在这种情况下,即使弄清楚该函数中隐含的匹配规则,也需要花费一些精力既mday
与wday
是非*
,是(month AND hour AND minute AND (mday OR wday))
。
基于此,再结合文档避免明确告诉我们mday匹配和wday匹配之间的布尔关系的方式,我猜想写新cron的人并没有考虑这些术语。他们考虑的不是5个布尔值的组合(直接对应于中的5个字段struct tm
),而是考虑一组4个问题:
这是正确的月份吗?
今天正确吗?
现在是正确的时间吗?
是正确的分钟吗?
这自然会导致天比较以自己的方式组合在一起,然后再将其他所有内容进行“与”运算。也许SysV cron作者只是做了当时感觉很明显的事情,而没有检查与旧cron的兼容性或思考“每月的第一个星期六”之类的用例。