如何指导cron每隔一周执行一次工作?
我想通过在每天的特定时间每周二执行的cron来执行一个任务。 每个星期二都很简单:
0 6 * * Tue
但是如何在“每个第二个星期二”(或者如果你更喜欢 – 每隔一周)做到这一点呢? 我不想在自己的脚本中实现任何逻辑,但只保留在cron的定义。
怎么样,即使它没有在前五个字段中完全定义,它仍然保留在crontab
:
0 6 * * Tue expr `date +\%W` \% 2 > /dev/null || /scripts/fortnightly.sh
回答
修改你的星期二cron逻辑, 从那个纪元开始每隔一周执行一次。
知道一周有604800秒(忽略DST变化和闰秒,谢谢),并使用GNUdate:
0 6 * * Tue expr `date +\%s` / 604800 \% 2 >/dev/null || /scripts/fortnightly.sh
在旁边
日历算术令人沮丧。
@ xahtep的回答非常棒,但是,正如@Doppelganger在评论中指出的那样 ,它在某些年份会失败。 date
实用程序的“每周”说明符都不能在这里帮助。 一月初的一些周二将不可避免地重复上周最后一个星期的平价:2016-01-05(%V),2018-01-02(%U)和2019-01-01(%W) 。
pilcrow的答案是伟大的。 然而,这会导致每周甚至每周运行一次fortnightly.sh脚本(从时代开始)。 如果你需要脚本运行几个星期,你可以稍微调整他的答案:
0 6 * * Tue expr \( `date +\%s` / 604800 + 1 \) \% 2 > /dev/null || /scripts/fortnightly.sh
将1更改为0会将其移回到几周。
也许有点愚蠢,但也可以创build两个cronjobs,每个第一个星期二和第三个星期一。
第一个cronjob:
0 0 8 ? 1/1 TUE#1 *
第二个cronjob:
0 0 8 ? 1/1 TUE#3 *
不知道这里的语法,我用http://www.cronmaker.com/来做这些。;
每第三周怎么样?
这是我的build议:
0 6 * * Tue expr `date +\%W` \% 3 == 0 > /dev/null || /scripts/fortnightly.sh
… 要么 …
0 6 * * Tue expr `date +\%W` \% 3 == 1 > /dev/null || /scripts/fortnightly.sh
…或者当然…
0 6 * * Tue expr `date +\%W` \% 3 == 2 > /dev/null || /scripts/fortnightly.sh
…取决于周旋转。
如果你只想每个星期二的第二周:
00 06 * * 2#2
我发现上述方法的一些其他限制可能会在某些边缘情况下失败。 例如,考虑:
@xahtep和@Doppelganger在上面的某些年份边界讨论了使用
%W
问题。@ pilcrow的答案在一定程度上解决了这个问题,但是它也会在某些边界上失败。 本文和其他相关主题中的答案使用一天(相对于一周)中的秒数,由于相同的原因,这也在某些边界上失败。
这是因为这些方法依赖UTC时间(date+%s)。 考虑一下我们在每周二第一个星期二凌晨1点和晚上10点的时候做一个工作的情况。
假设GMT-2:
- 当地时间凌晨1点=上午11点UTC
- 当地时间晚上10点= 今天 8点UTC
如果我们每天只检查一次,这不会是一个问题,但如果我们多次检查 – 或者如果我们接近UTC时间和夏令时发生,脚本将不会认为这些是同一天。
为了解决这个问题,我们需要根据我们的本地时区而不是UTC来计算UTC的偏移量。 我在BASH中找不到一个简单的方法,所以我开发了一个解决scheme,它使用Perl中的快速内存来计算从几秒钟内UTC的偏移量。
此脚本利用date+%z,输出本地时区。
Bash脚本:
TZ_OFFSET=$( date +%z | perl -ne '$_ =~ /([+-])(\d{2})(\d{2})/; print eval($1."60**2") * ($2 + $3/60);' ) DAY_PARITY=$(( ( `date +%s` + ${TZ_OFFSET} ) / 86400 % 2 ))
那么,要确定一天是偶数还是偶数:
if [ ${DAY_PARITY} -eq 1 ]; then ... else ... fi
Cron提供“隔一个”语法“/ 2”。 只需按照适当的时间单位字段中的“/ 2”,它会每隔一段时间执行一次cronjob。 在你的情况下…
0 6 * * Tue/2
上面应该每隔一个星期二执行一次。
语法“/ 2”不是星期几。 所以我添加到上面的聪明只是使用MonthDay提交1,15。
0 6 1,15 * * /scripts/fornightly.sh> / dev / null 2>&1
为什么不喜欢
0 0 1-7,15-21,29-31 * 5
这是否合适?