是否可以安排一个 cron 作业,每三周仅在周三(上午 8 点)运行一次?或者,如果不可能的话,每 27 天或更短时间运行一次作业,但在周三上午 8 点运行一次。
答案1
每个星期三执行以下代码:
tspath="/path/to/timestamp" && [ -f ${tspath} ] && \
[ `date +%s` -lt $(($(cat ${tspath})+20*86400)) ] || \
{ date +%s > ${tspath}; your_command; }
其中/path/to/timestamp
是任意路径名(最初不存在),通常位于用户主目录中的某个位置(为了避免符号链接攻击,请勿使用其他用户可以写入的目录)。该代码的工作原理如下:
- 如果此路径名尚不存在,则我们使用当前日期作为其内容来创建它,然后运行命令。日期用自某个称为纪元的起源以来的秒数表示。
- 如果此路径名存在(在这种情况下,假定它是由此脚本创建的),则它指定上次运行命令的日期。我们向该日期添加 20 天(20*86400 秒),并将结果与当前日期进行比较。如果至少过去了 20 天,我们将使用当前日期更新路径名内容并运行命令。
由于此代码每周三(上午 8 点)通过 cron 运行,因此该命令将每 3 周运行一次(在 1 或 2 周后,还没有过去 20 天)。
请注意,即使机器在第三个星期三之前关闭,此解决方案仍然有效。如果由于某种原因,机器在第三个星期三关闭,那么该命令将在机器打开的下一个星期三运行(该问题要求仅在星期三上午 8 点运行该命令)。
编辑:您可以将上述代码放入其自己的文件中(将其作为脚本执行)或直接放入 crontab 文件中的单行中(在这种情况下,删除反斜杠)。
答案2
如果您使用 GNU/Linux 和 dillon 的crond
(查找dcron
适合您的发行版的软件包),您可以使用 crontab 的更细粒度的语法,如中所述man 1 crontab
0 8 * * wed ID=job1 FREQ=20d your_job
your_job
如果自上次执行以来已过去至少 20 天,则该命令将于周三上午 8 点执行。
答案3
如果您已经有一个 cron 但不是dcron
并且不想更改它,您可以使用此 cron 作业:
0 8 * * wed n=0 && [[ -e /home/user/.cronjob && -r /home/user/cronjob ]] && read n < /home/user/.cronjob ; [[ $n == 0 ]] && your_actual_job ; echo $(( (n+1) \% 3 )) > /home/user/.cronjob
这将进行某种簿记。每个星期三,cron 作业都会运行。它将获取 中写入的值.cronjob
,该值可以是 0、1 或 2。如果为 0,则运行实际作业。然后,该值以模 3 递增并写回.cronjob
。
请注意“%”之前的“\”。这是必需的,因为 cron 以特殊方式解释“%”。