CRON 多快被触发?

How quickly is CRON triggered?

第一个例子

假设我有一个 CRON 作业

 30 2 * * * ....

然后每次 运行 晚上(当地时间)2:30 时都会 运行。

现在假设我有时区 Europe/Germany,现在是 2017 年 10 月 29 日(切换 DST 的那一天)。那么这个 CRON 作业会 运行 两次,对吧?

第二个例子

假设我有时区 Europe/Germany 和 CRON 作业

 30 11 * * * ....

由于德国在 11:30 从未有过 DST 更改,这不会造成干扰。但用户可以更改当地时间。非常清楚:这个问题不是关于 DST

对于以下测试用例,我想知道 if/how CRON 作业的调度频率:

  1. 在11:29:58.0,用户设置时间为11:31:00
  2. 在11:29:59.1,用户设置时间为11:31:00
  3. 在11:29:59.6,用户设置时间为11:31:00
  4. 在11:30:01.0,用户设置时间为11:29:59.7 - 之后直接执行CRON吗?

他们归结为 CRON 触发的速度有多快?,其中第 4 个问题也有问题,即 CRON 是否存储它已经在那一分钟执行。

同一问题的另一个变体:

  1. 在 11:29:59,NTP 服务将时间更正为 11:31:00 - 当天是否会执行作业?

在 mac OS:

$> man cron
...
Available options:

 -s      Enable special handling of situations when the GMT offset of the local timezone changes, such as the switches between the standard time and daylight saving time.

         The jobs run during the GMT offset changes time as intuitively expected.  If a job falls into a time interval that disappears (for example, during the switch from standard time) to daylight saving time
         or is duplicated (for example, during the reverse switch), then it is handled in one of two ways:

         The first case is for the jobs that run every at hour of a time interval overlapping with the disappearing or duplicated interval.  In other words, if the job had run within one hour before the GMT
         offset change (and cron was not restarted nor the crontab(5) changed after that) or would run after the change at the next hour.  They work as always, skip the skipped time or run in the added time as
         usual.

         The second case is for the jobs that run less frequently.  They are executed exactly once, they are not skipped nor executed twice (unless cron is restarted or the user's crontab(5) is changed during
         such a time interval).  If an interval disappears due to the GMT offset change, such jobs are executed at the same absolute point of time as they would be in the old time zone.  For example, if exactly
         one hour disappears, this point would be during the next hour at the first minute that is specified for them in crontab(5).

 -o      Disable the special handling of situations when the GMT offset of the local timezone changes, to be compatible with the old (default) behavior.  If both options -o and -s are specified, the option
         specified last wins.

要自信地回答这个问题,最简单的方法是查看 cron 守护程序的源代码。网上有几个版本像this, or you can use apt-get source cron.

cron 中的滴答周期是重复休眠一分钟,或者如果有工作要做则更短。从睡眠中醒来后,它会立即检查时间并将结果视为以下 wakeupKind 值之一:

  • 预计时间 - 运行 我们期望的任何工作
  • 向前小跳(最多 5 分钟)- 运行 中间分钟的作业
  • 中等向前跳转(最多 3 小时,因此这将包括从 spring 开始的夏令时)- 运行 首先是任何通配符作业(因为赶上可能需要一分钟以上),然后赶上中间的固定时间工作
  • 大跳跃(3 小时或更长时间)- 从当前时间开始
  • 向后跳转(最多 3 小时,因此包括 DST 结束)- 因为任何固定时间作业都已经 'probably' 运行,只有 运行 任何通配符作业,直到时间又被赶上了

如有疑问,来源评论这些 wakeupKind values 清楚。


编辑

要跟进 sleep() 是否会受到时钟更改的影响,答案似乎间接地存在于 Linux 手册页中。

  • 首先 sleep() function 的注释确认由 nanosleep()
  • 实现
  • nanosleep() 的注释说 Linux 使用 CLOCK_MONOTONIC 时钟测量时间(尽管 POSIX.1 说不应该)
  • clock_settime()的文档中向下滚动一点可以看到CLOCK_MONOTONIC的解释,其中解释它不受系统时间跳跃的影响,但会受到增量NTP的影响样式时钟同步调整。

总而言之,系统管理员风格的时钟更改不会对 sleep() 产生影响。但是,例如,如果 NTP 调整进来并说 'gently' 提前时钟,cron 将经历一系列稍微短的 sleep() 函数调用。

您实际上是在问两个相关的问题。一般的答案是这取决于 [1],但我会根据我现在正在使用的 Debian Linux 安装来回答:

cron 如何处理 DST 更改和其他 'special' 时间相关事件?

在我的 Debian Linux 系统 cron 句柄 'DST and other time-related changes/fixes'(根据手册页)因此作业 不会 得到 运行 两次或由于 DST 等更改而跳过。 (有关详细信息,请参阅 https://debian-handbook.info/browse/stable/sect.task-scheduling-cron-atd.html)关于您在第二个问题中提出的第 5 点,我希望这些相同的设施能够处理与 NTP 相关的时间跳跃,但不确定。

cron 多久触发一次,它接收我的 crontab 更改的速度有多快?

同样,在我的 Debian Linux 系统上,cron 守护进程每分钟唤醒一次,并将检测并利用自上一个 check/run 一分钟前以来的任何 crontab 更改。请注意,不能保证 cron 在 12:00:00 或 12:00:59 或两者之间的任何特定时间触发(仅在时间为 12:00:?? 时触发),因此如果您在 12:00:17 处更改了一个 crontab,但在 12:00:13 处触发了 cron,直到下一个 运行(最有可能在 12:01:13 之前,您的更改不会被获取由于 Linux 调度程序,可能会有少量差异)

[1] 这取决于...

准确的答案绝对取决于平台 (Linux/Unix/BSD/OS X/Windows) 和 cron 的特定实现(几十年来,Vixie cron 的衍生产品在 Linux 和 BSD 每 https://en.wikipedia.org/wiki/Vixie_cron)。如果您 运行 正在使用 Linux 之外的东西,您的实现的手册页/文档应该提供详细信息,说明它 运行 的频率、获取修改后的 crontab 的详细信息, DST 处理等。如果您真的需要了解具体细节,df778899 是正确的,您应该根据需要查看实现的源代码...因为有时 software/documentation 是错误的。

有许多 cron 系统的实现(参见 here)。最常用的 cron 之一是 Vixie cron。它的手册页指出:

Daylight Saving Time and other time changes

Local time changes of less than three hours, such as those caused by the Daylight Saving Time changes, are handled in a special way. This only applies to jobs that run at a specific time and jobs that run with a granularity greater than one hour. Jobs that run more frequently are scheduled normally.

If time was adjusted one hour forward, those jobs that would have run in the interval that has been skipped will be run immediately. Conversely, if time was adjusted backwards, running the same job twice is avoided.

Time changes of more than 3 hours are considered to be corrections to the clock or the timezone, and the new time is used immediately.

source: man 8 cron

我相信这回答了你的大部分观点。

除了第五点:

  1. At 11:29:59, the NTP service corrects the time to 11:31:00 - will the job be executed that day at all?

首先,如果 NTP 将时间校正超过一分钟,那么您的时钟就非常糟糕!这不应该经常发生。一般在启用NTP时可能会有这样的步骤,但之后应该会少很多。

在任何情况下,如果 DeltaT 不是很高,通常低于 125 毫秒,您的系统将 转换 时间。 Slewing时间的意思是改变软件时钟的虚拟频率,使时钟走得更快或更慢,直到达到要求的校正。延长时钟时间也可能需要一些时间。例如标准 Linux 以每秒 0.5 毫秒的速率调整时间。

这意味着,(在 Vixie cron 的假设下,可能还有许多其他人):

  • 如果 NTP 跳转超过 3 小时,作业将被跳过
  • 如果 NTP 跳跃少于 3 小时但超过 125 毫秒,Vixie cron 通过假设时间跳跃的概念很好地处理了这项工作。
  • 如果 NTP 将时间更正为小于 125 毫秒,cron 不会注意到由于回转引起的时间跳跃。

有趣的信息: