从 Vixie cron 再往前走一步,“wday OR mday”逻辑出现在 System V cron 中,但 System III 或更早版本中没有。
在 Paul Vixie 编写他的 cron 替代品之前,BSD cron 就像 SysIII 和更早版本的 cron。所有 5 个字段都进行了 AND 运算。 4.4 后的 BSD 采用了 Vixie cron,使其更像 SysV。
所以不要问(责备)Vixie。他只是在克隆 SysV。
SysV 为什么要这样做?我不知道,但我会尝试提供一些部分线索......
要尝试了解 SysV 中发生了什么,查看源代码(before - SysIII 和 after - SVr4)以及新行为的文档会有所帮助:
注意:可以通过两个字段(月中的天和周中的天)来指定天数。如果两者都被指定为元素列表,则两者都被遵守。
(摘自 SunOS 4.1.3 手册页。在这方面似乎是 SysV-ish。在 Paul Vixie 编写他的替代品之前,BSD cron 从未有过这种行为。)
“两者都遵守”是使用 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 个布尔值的组合(直接对应于 struct tm 中的 5 个字段),而是考虑一组 4 个问题:
- 月份是否正确?
- 今天是正确的日子吗?
- 现在是正确的时间吗?
- 分钟是否正确?
这自然会导致日期比较以自己的方式组合,然后再将其他所有内容组合在一起。也许 SysV cron 作者只是做了当时感觉很明显的事情,没有检查与旧 cron 的兼容性或思考“每个月的第一个星期六”之类的用例。