当同时指定星期几和星期几时,为什么crontab使用OR? [英] Why crontab uses OR when both day of month and day of week specified?

查看:389
本文介绍了当同时指定星期几和星期几时,为什么crontab使用OR?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个著名的问题",当crontab行同时包含星期几和月份中的某天时,cron使用OR来计算出一天来触发命令. 例如.如果你写

* * 13 * 5 command

该命令将在每月的每个星期五和每个第13天执行,而不仅是在第13个星期五执行. 这与其他字段的格式相矛盾(当您写入30 2 * * *时,仅在-小时和分钟-都与您指定的完全相同时才执行;对于其他所有字段,除了DoW和DoM都指定时,都将相同).

所以我的问题是:是否有导致此异常的特定原因?我的意思是,应该有一个原因,但是我似乎找不到. (相反,我在互联网上看到很多人希望将这些领域与其他领域一样对待-采用"AND策略",恰好是"5月13日星期五"或"5月2日星期四"之类的东西.) /p>

解决方案

再回到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中发生的情况,请查看源代码(之后-SVr4 )以及新行为的文档:

注意:可以通过两个字段(月中的某天和一周中的某天)来指定天数.如果将两者都指定为元素列表,则都将遵守.

(摘录自 OpenSolaris 手册页中:

可以通过两个字段(月中的天和周中的天)来指定天数.如果指定为元素列表,则都遵守.

SysV代码是完整的重写.它的功能之一是长时间没有工作要运行时会长时间睡眠. (较早的cron每分钟都会醒来,并将当前时间与所有作业规范进行比较.)计算功能(next_time)顶部的注释说明:NOTE: this routine is hard to understand.

确实很难理解.它是查找此crontab行的下一个执行时间"函数,而不是确定当前时间是否与此crontab行匹配"的函数,因此需要花费一些精力才能弄清楚该函数中隐含的匹配规则,当mdaywday都不是*,都是(month AND hour AND minute AND (mday OR wday)).

基于此,再加上文档避免显式地告诉我们mday匹配和wday匹配之间的布尔关系的方式,我猜想写新cron的人并没有在考虑这些问题条款.他们考虑的不是5个布尔值的组合(直接与struct tm中的5个字段相对应),而是考虑一组4个问题:

  1. 现在是正确的月份吗?
  2. 今天正确吗?
  3. 现在是正确的时间吗?
  4. 现在是正确的分钟吗?

这自然会导致天比较以自己的方式进行组合,然后再将其他所有内容进行与"运算.也许SysV cron作者只是做了当时感觉很明显的事情,而没有检查与旧cron的兼容性或思考每月的第一个星期六"之类的用例.

It is a famous "problem" that when a crontab line contains both day of week and day of month cron uses OR for figuring out a day to fire the command. E.g. if you write

* * 13 * 5 command

the command will execute on every Friday and every 13th day of month, not only on the Fridays that are 13th. This contradicts the format for the other fields (when you write 30 2 * * * it will be executed only when both - hour AND minute - are exactly what you specified; same for all other fields except for DoW and DoM when they are both specified).

So my question is: is there a specific reason for this exception? I mean, there should be a reason, but I can't seem to find it. (And instead I see a lot of people in the internets who would like for these fields to be treated like any other - with the "AND strategy", precisely for stuff like "Friday 13th" or "2nd Thursday of May".)

解决方案

Going back a step further from Vixie cron, the "wday OR mday" logic was present in System V cron, but not System III or anything earlier.

Before Paul Vixie wrote his cron replacement, BSD cron was like the SysIII-and-earlier cron. All 5 fields were ANDed. The post-4.4 BSDs adopted Vixie cron, making themselves more SysV-like.

So don't ask (blame) Vixie. He was just cloning SysV.

Why did SysV do that? I don't know but I'll try to provide some partial clues...

To try to understand what happened in SysV, it helps to look at the source (before - SysIII and after - SVr4) and also the documentation of the new behavior:

Note: the specification of days may be made by two fields (day of the month and day of the week). If both are specified as a list of elements, both are adhered to.

(Excerpt from SunOS 4.1.3 man page. It appears to be SysV-ish in this area. BSD cron never had this behavior before Paul Vixie wrote his replacement.)

"Both are adhered to" is a confusing substitute for a normal boolean expression using ANDs and ORs. It's still there in the OpenSolaris man page a couple of decades later:

The specification of days can be made by two fields (day of the month and day of the week). Both are adhered to if specified as a list of elements.

The SysV code is a complete rewrite. One of its features is that it sleeps for a long time when no jobs are due to run soon. (The older cron wakes up every minute and compares the current time to all job specifications.) A comment at the top of the calculation function (next_time) explains: NOTE: this routine is hard to understand.

It is indeed hard to understand. It is a "find next execution time for this crontab line" function, instead of a "decide whether the current time matches this crontab line" function, so it takes some effort to even figure out that the matching rule implicit in this function, when both mday and wday are non-*, is (month AND hour AND minute AND (mday OR wday)).

Based on that, combined with the way the documentation avoids explicitly telling us the boolean relationship between mday matching and wday matching, I'm going to guess that the person who wrote the new cron just wasn't thinking about it in those terms. They were thinking not about a combination of 5 booleans (corresponding directly to 5 fields in a struct tm), but about a set of 4 questions:

  1. Is it the correct month?
  2. Is it the correct day?
  3. Is it the correct hour?
  4. Is it the correct minute?

This leads naturally to the day comparisons being combined in their own way before ANDing everything else together. Maybe the SysV cron author just did what felt like the obvious thing at the time, without checking for compatibility with the old cron or pondering use cases like "first Saturday of every month".

这篇关于当同时指定星期几和星期几时,为什么crontab使用OR?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆