如何指示 cron 每两周执行一次作业?

2024-10-11 08:36:00
admin
原创
90
摘要:问题描述:我想通过 cron 运行一个作业,该作业将在每月第二个星期二的给定时间执行。每个星期二的执行很简单:0 6 * * Tue 但是如何实现“每隔一个星期二”(或者如果你愿意 - 每隔一周)呢?我不想在脚本本身中实现任何逻辑,而只在 cron 中保留定义。解决方案 1:回答修改您星期二的 cron 逻辑...

问题描述:

我想通过 cron 运行一个作业,该作业将在每月第二个星期二的给定时间执行。每个星期二的执行很简单:

0 6 * * Tue

但是如何实现“每隔一个星期二”(或者如果你愿意 - 每隔一周)呢?我不想在脚本本身中实现任何逻辑,而只在 cron 中保留定义。


解决方案 1:

回答

修改您星期二的 cron 逻辑,使其从纪元开始每隔一周执行一次。

知道一周有 604800 秒(忽略夏令时变化和闰秒,谢谢),并使用 GNU 日期:

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)。

解决方案 2:

crontab这样怎么样,即使前五个字段没有明确定义,它也会保留它:

0 6 * * Tue expr `date +%W` % 2 > /dev/null || /scripts/fortnightly.sh

解决方案 3:

类似于

0 0 1-7,15-21 * 2

将会在每月的第一和第三个星期二发生。

注意:不要将其与 vixie cron(包含在 RedHat 和 SLES 发行版中)一起使用,因为它会在月份和星期几字段之间生成或,而不是与。

解决方案 4:

可能有点傻,但人们也可以创建两个 cronjob,每个第一个星期二执行一个,每第三个星期二执行一个。

第一个 cronjob:

0 0 8 ? 1/1 TUE#1 *

第二个 cronjob:

0 0 8 ? 1/1 TUE#3 *

不确定这里的语法,我使用http://www.cronmaker.com/来制作这些。

解决方案 5:

pilcrow 的回答很棒。但是,它导致 fortnightly.sh 脚本每双周运行一次自纪元以来)。如果您需要脚本在奇数周运行,您可以稍微调整他的答案:

0 6 * * Tue expr ( `date +%s` / 604800 + 1 ) % 2 > /dev/null || /scripts/fortnightly.sh

将 1 改为 0 将使其移回偶数周。

解决方案 6:

如果您想根据给定的开始日期执行此操作:

0 6 * * 1 expr ( `date +%s` / 86400 - `date --date='2018-03-19' +%s` / 86400 ) % 14 == 0 > /dev/null && /scripts/fortnightly.sh

从 2018-03-19 开始每隔一个星期一触发

表达式为:如果...则于星期一早上 6 点运行。

1 - 获取今天的日期(以秒为单位),除以一天的秒数,以转换为自纪元以来的天数

2 - 对开始日期执行相同操作,将其转换为自纪元以来的天数

3 - 了解两者之间的区别

4 - 除以 14 并检查余数

5- 如果余数为零,则表示您处于两周的周期

解决方案 7:

我发现上述方法还有一些其他限制,在某些极端情况下可能会失败。例如,考虑:

@xahtep 和 @Doppelganger 讨论了%W上述使用某些年份界限的问题。

@pilcrow 的答案在某种程度上解决了这个问题,但它也会在某些边界上失败。本主题或其他相关主题中的答案使用一天中的秒数(而不是一周),由于同样的原因,它们也会在某些边界上失败。

这是因为这些方法依赖于 UTC 时间(日期 +%s)。考虑一下我们每月第二个星期二凌晨 1 点和晚上 10 点运行作业的情况。

假设GMT-2:

  • 当地时间凌晨 1 点 =昨天晚上 11 点(UTC)

  • 当地时间晚上 10 点 = UTC今天晚上 8 点

如果我们每天只检查一次,这将不是问题,但如果我们检查多次 - 或者如果我们接近 UTC 时间并且发生夏令时,脚本就不会将这些视为同一天。

为了解决这个问题,我们需要根据我们当地的时区而不是 UTC 来计算与 UTC 的偏移量。我在 BASH 中找不到简单的方法来做到这一点,所以我开发了一个解决方案,使用 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

解决方案 8:

这里有很多不错的答案。根据评论,我看到了相当多的困惑和沮丧。我给出这个答案的目的不仅是回答 OP 的问题如何指示 cron 每两周执行一次作业?,而且还为将来可能阅读此内容的人消除一些困惑。

TL;DR:

crontab 条目如下所示:

<minute> <hour> * * <Day of Week> expr \( $( date+\%s ) \/ 604800 \% 2 \) > /dev/null && <command to run on odd weeks> || <command to run on even weeks>

Crontab 条目:根据手册页,

所有 [用 ] 编写的 crontab 条目都具有以下格式:
1:要执行 [命令] 的小时中的分钟
范围:0-59
2:要执行 [命令] 的一天中的小时
范围:0-23 3:要执行 [命令] 的月份中的日期
范围:1-31
4:要执行 [命令] 的月份
范围:1-12
5:要执行 [命令] 的星期几
范围:检查手册页,可能是 0-6、1-7 或 0-7
6:要执行的命令
注意,还有 @ 值,在这里我就不讨论了。crontab -e

*nix 的某些版本允许表达式:

*/2= 范围内的每个偶数

1 + */2= 范围内的每个奇数

1,15= 第一和第十五

2-8= 第二到第八(含)

有些版本还允许使用人类可读的单词,例如二月或星期三。

对于月份,*/2 将在二月、四月、六月、八月、十月、十二月执行。

对于星期几,*/2 将在每双日运行 - 请查看手册页以了解星期几是如何编号的。Tue/2 不是有效的表达式。

人类可读性(日历)的困境

你需要知道一些常量:一年

有 365.2464(为了方便,我们将其四舍五入为 365)。一年

有 12 个。一周

有 7。一天

有 86,400秒。

因此,

1 个月为 4-1/3 周

(即 3 个月为 13 周),

1 年为 52-1/7 周

日历数学的祸根:

半月 = 每半月 = 2x/月 = 每年 24 次。

双周 = 每隔一周(每两周)= 每年 26 次。

注意:这些术语经常被误用。

有些年份有 51 周,有些有 53 周,大多数有 52 周。如果我的 cron 每奇数周运行一次(date +%W模 2),并且一年有 51 或 53 周,它也会在下一周运行,即新年的第一周。相反,如果我的 cron 每偶数周运行一次,它将跳过 2 周。这不是我想要的。

CRON 可以支持半月,但不支持双周!半月:

每月的第一天总是在 1 号和 7 号之间。下半周总是在 15 号和 21 号之间。半月

有两个值,一个在上半月,另一个在下半月。例如:

2,16

Unix 时间

从非常高的层次来看,*nix 时间有 2 个值:

date +%s= 自纪元 (01/01/1970 00:00:00) 以来的

date +%N秒数 = 秒的小数部分(以纳秒为单位)

因此,*nix 中的时间是date +%s.%N

*Nix 使用纪元时间。/etc/shadow 文件包含上次更改密码的日期。它是 %s 除以 86,400 的整数部分。

Factino

GPS 卫星测量时间的方式是“自纪元时间以来的周数”和“一周内的(小数)秒数”。

注意:纪元周与年份无关。年份有 51 周、52 周还是 53 周并不重要。纪元周永不滚动。

双周时间算法

Nix 日期中 +%W 是一年中的周数,而不是纪元周。 nix 没有纪元周值,但可以计算出来。

纪元周 = 整数(纪元秒 / 每天秒数 / 每周天数)

每两周 = 纪元周模数 2

每两周的值始终为 0 或 1,因此,当 Fortnightly = 0 时运行命令会在每个偶数周运行,而 1 = 每个奇数周运行。

每两周计算)

第一种方式(bc):

date +"%s / 604800 % 2" | bc

这将生成“[Epoch Seconds] / 604800 % 2”

然后,该答案被发送到 bc,这是一个基本的计算器,它会进行计算并将答案回显到 STDOUT,并将任何错误回显到 STDERR。

返回代码为 0。

第二种方法(expr):

在这种情况下,将表达式发送给 expr 并让其进行计算
expr $( date +%s ) / 604800 % 2

expr 命令进行计算,将答案回显到 STDOUT,将错误回显到 STDERR。如果答案为 0,则返回代码为 1,否则,返回代码为 0。

通过这种方式,我不关心答案是什么,只关心返回代码。考虑一下:

$ expr 1 % 2 && echo Odd || echo Even
1
Odd 
$ expr 2 % 2 && echo Odd || echo Even 
0 
Even

由于结果无关紧要,我可以将 STDOUT 重定向到 /dev/null。在这种情况下,我将保留 STDERR,以防万一发生意外情况,我会看到错误消息。

Crontab 条目

在 crontab 中,百分号和括号具有特殊含义,因此需要用反斜杠 () 进行转义。

首先,我需要决定是在偶数周还是奇数周运行。或者,也许在奇数周运行 Command_O,在偶数周运行 command_E。然后,我需要转义所有特殊字符。

由于 expr 仅评估 WEEKS,因此需要指定要评估的特定星期几(和时间),例如每周二下午 3:15。因此,我的 crontab 条目的前 5 个文件(时间条目)将是:

15 3 * * TUE

我的 cron 命令的第一部分将是 expr 命令,STDOUT 发送到 null:

expr \( $( date+\%s ) \/ 604800 \% 2 \) > /dev/null

第二部分将是评估器,&&或者||

第三部分将是我想要运行的命令(或脚本)。如下所示:

expr \( $( date+\%s ) \/ 604800 \% 2 \) > /dev/null && <command_O> || <command_E>

希望这能澄清一些困惑

解决方案 9:

尝试一下

0 0 1-7,15-21 * 2

该活动每月举办两次,每次都在星期二,且间隔至少一周。

解决方案 10:

30 4 /2 1

如果是周一,则每月第二天早上 4:30

解决方案 11:

如果您只想要第二周的每个星期二:

00 06 2#2

解决方案 12:

Cron 提供了“每隔一次”语法“/2”。只需在相应的时间单位字段后加上“/2”,它就会“每隔一次”执行 cronjob。对于您的情况...

0 6 * * Tue/2

上述操作应每隔一个星期二执行一次。

解决方案 13:

语法“/2”与工作日不符。因此,我对上面的智能补充是简单地在 MonthDay 字段上使用 1,15。

0 6 1,15 /scripts/fornightly.sh > /dev/null 2>&1

解决方案 14:

为什么不像

0 0 1-7,15-21,29-31 * 5

这样合适吗?

解决方案 15:

0 0 /14 *

每月 14 日 00:00 运行

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   609  
  在现代项目管理中,资源的有效利用是确保项目成功的关键因素之一。随着技术的不断进步,越来越多的工具和软件被开发出来,以帮助项目经理和团队更高效地管理资源。本文将介绍10款工具,这些工具可以帮助项目团队提升资源利用效率,从而实现项目目标。禅道项目管理软件禅道项目管理软件是一款开源的项目管理工具,广泛应用于软件开发和其他行业...
项目管理系统   3  
  在项目管理领域,软件工具的不断升级和创新是推动效率和协作的关键。2024年,众多项目管理软件将迎来一系列令人期待的升级功能,这些新特性不仅将提升团队的工作效率,还将增强用户体验和数据分析能力。本文将详细介绍10款项目管理软件的最新升级功能,帮助项目经理和团队成员更好地规划和执行项目。禅道项目管理软件禅道项目管理软件一直...
开源项目管理工具   2  
  信创国产系统的10个关键厂商及其技术生态随着全球信息技术格局的不断演变,信创(信息技术应用创新)产业作为国产化替代的重要阶段,正逐步成为推动我国信息技术自主可控、安全可靠的核心力量。信创产业不仅关乎国家信息安全,也是数字经济高质量发展的关键支撑。本文将深入探讨信创国产系统中的10个关键厂商及其技术生态,分析它们在信创浪...
项目管理流程   0  
  在探讨项目管理的广阔领域中,成功并非偶然,而是精心策划、高效执行与持续优化的结果。项目管理的成功之道,可以从明确的目标设定与规划、高效的团队协作与沟通、以及灵活的风险管理与适应变化这三个核心方面进行深入解析。每个方面都是项目成功的基石,它们相互交织,共同支撑起项目的顺利推进与最终成就。明确的目标设定与规划项目管理的首要...
建筑工程项目管理规范   0  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用