当我的服务器自动使用 DST 时,如何使用 cron 安排在非 DST 感知应用程序上实现夏令时的脚本?

Nei*_*den 5 server 8.04 time cron-jobs

我的服务器(运行 ubuntu 8.04LTS 服务器)现在报告时间为 BST 晚上 9:38。BST(英国夏令时)比 UTC(或格林威治标准时间,如果你真的想搞混的话)早 1 小时

议会法案规定我们在英国使用 BST

从格林威治标准时间 3 月最后一个星期日上午一点开始到格林威治标准时间 10 月最后一个星期日上午一点结束的时间段。

在 cron 中安排这个没有问题,但我不知道我应该使用什么日期格式/时区。我是否将它设置为在凌晨 1 点前进但在结束时在凌晨 2 点返回?如果机器使用 BST,这是有道理的,但我担心该 cron 不会在凌晨 2 点触发,因为系统时钟可能会在有机会触发之前重置回凌晨 1 点 - 从而使我的脚本运行晚了 1 小时。

或者它只是使用UTC?

Ric*_*rri 3

答案在于 cron 源(您可以通过 cron 获取apt-get source cron),特别是在文件 159--272 行的主循环中cron.c

crond睡眠一分钟,然后醒来并查询系统时间,将其与自己的时间概念进行比较(即,如果没有改变时钟,现在是什么时间)。根据实际时间与预期时间的差异,crond采取不同的行动;其中两个与您的情况相关:

  1. 时间快进超过 5 分钟但不到 3 小时(夏令时开始):cron 运行在实际时间安排的通配符作业,以及在计算时间和实际时间之间的固定时间安排的任何作业。相关来源位于第 221--247 行:

      /*
       * case 2: timeDiff is a medium-sized positive number,
       * for example because we went to DST run wildcard
       * jobs once, then run any fixed-time jobs that would
       * otherwise be skipped if we use up our minute
       * (possible, if there are a lot of jobs to run) go
       * around the loop again so that wildcard jobs have
       * a chance to run, and we do our housekeeping
       */
      Debug(DSCH, ("[%d], DST begins %d minutes to go\n",
          getpid(), timeRunning - virtualTime))
      /* run wildcard jobs for current minute */
      find_jobs(timeRunning, &database, TRUE, FALSE);
    
    
      /* run fixed-time jobs for each minute missed */ 
      do {
         if (job_runqueue())
                 sleep(10);
         virtualTime++;
         find_jobs(virtualTime, &database, FALSE, TRUE);
         set_time();
      } while (virtualTime< timeRunning &&
          clockTime == timeRunning);
      break;
    
    Run Code Online (Sandbox Code Playgroud)
  2. 时间倒退了不到 3 小时(DST 结束):仅运行通配符作业,跳过固定计划作业,因为它们已经运行。相关来源位于第 247--258 行:

    /*
     * case 3: timeDiff is a small or medium-sized
     * negative num, eg. because of DST ending just run
     * the wildcard jobs. The fixed-time jobs probably
     * have already run, and should not be repeated
     * virtual time does not change until we are caught up
     */
    Debug(DSCH, ("[%d], DST ends %d minutes to go\n",
        getpid(), virtualTime - timeRunning))
    find_jobs(timeRunning, &database, TRUE, FALSE);
    break;
    
    Run Code Online (Sandbox Code Playgroud)

因此,当进入 DST 时,您应该没有问题:您的脚本将运行(在时间跳跃之前或之后立即运行)。

退出 DST 时,如果您将工作恰好安排在 1 点,那么您的(固定时间)工作可能会被跳过。我的建议是将跑步安排在 1 点之前 1 分钟或 2 点(或之后)。