如何定义在每个月的第一个星期一执行脚本的 cron 表达式?
How to define a cron expression that execute a script in the first monday of each month?
我有一个这样的脚本:
* * * * * path/to/my/script.sh
我需要在每个月的第一个星期一定义每月一次的cron表达式“* * * * *”到运行。
crontab 语法无法定义所有可能的
人们可以想象的时期。例如,它不是直截了当的
如您所述,定义一个月的最后一个工作日或每个月的第一个星期一。
那么,最好的办法就是让script.sh
检查一下。
使用这样的东西:
if [ $(date +\%e) != $(ncal | awk '/Mo/ { print }') ]
then
exit
fi
每月的第一个星期一是该月前 7 天中唯一的星期一。因此,要在 1:02 AM 执行作业,请使用:
2 1 1-7 * * test $(date +\%u) -eq 1 && path/to/my/script.sh
前两项,数字1
和2
,设置分钟和小时。
第三项,1-7
,设置一个月中某天的允许范围。
第四项 *
是月份,我们允许所有月份匹配。
第五项*
设置星期几。 此字段与日期字段进行“或”运算。因此,在此处指定星期一没有用。如果我们这样做,cronjob 将在每个月的前 7 天 和 所有星期一 运行。
最后,我们有 test $(date +\%u) -eq 1
。这 returns 仅在星期一为真。由于紧随其后的 &&
,您的脚本将仅在每月前 7 天的星期一执行。
请注意,在 crontab 条目中,%
被视为换行符,除非它被转义。因为我们需要一个文字 %
,所以在上面的命令中用反斜杠转义了
有关其工作原理的更多信息,请参阅 man 5 crontab
。
备选
正如 twalberg 所指出的,同样的逻辑反过来也适用。我们可以 运行 每个星期一的 cronjob,然后测试那个星期一是否是该月的前 7 天之一:
2 1 * * Mon test $(date +\%e) -le 7 && path/to/my/script.sh
如果您使用 Debian 或 Debian 衍生产品附带的 cron,您可以使用:
0 0 */50,1-7 * MON path/to/my/script.sh
是的,它有效,但有点难以解释为什么。
首先,让我们考虑这个表达式:
0 0 1-7 * MON path/to/my/script.sh
这个将 运行 在日期 1-7 以及每周一举行。这几乎就是我们想要的,除了我们想要 day-of-month 和 day-of-week 字段之间的“AND”关系,而不是“OR”关系。
奇怪的额外 */50
位利用了 Debian cron 的表达式解析逻辑中的一个怪癖。它使 cron 认为 day-of-month 字段是通配符字段,并应用“AND”逻辑。
注意 – 这是一个 hack。如果您使用此表达式,请确保将其记录下来以避免以后混淆。
我有一个这样的脚本:
* * * * * path/to/my/script.sh
我需要在每个月的第一个星期一定义每月一次的cron表达式“* * * * *”到运行。
crontab 语法无法定义所有可能的 人们可以想象的时期。例如,它不是直截了当的 如您所述,定义一个月的最后一个工作日或每个月的第一个星期一。
那么,最好的办法就是让script.sh
检查一下。
使用这样的东西:
if [ $(date +\%e) != $(ncal | awk '/Mo/ { print }') ]
then
exit
fi
每月的第一个星期一是该月前 7 天中唯一的星期一。因此,要在 1:02 AM 执行作业,请使用:
2 1 1-7 * * test $(date +\%u) -eq 1 && path/to/my/script.sh
前两项,数字1
和2
,设置分钟和小时。
第三项,1-7
,设置一个月中某天的允许范围。
第四项 *
是月份,我们允许所有月份匹配。
第五项*
设置星期几。 此字段与日期字段进行“或”运算。因此,在此处指定星期一没有用。如果我们这样做,cronjob 将在每个月的前 7 天 和 所有星期一 运行。
最后,我们有 test $(date +\%u) -eq 1
。这 returns 仅在星期一为真。由于紧随其后的 &&
,您的脚本将仅在每月前 7 天的星期一执行。
请注意,在 crontab 条目中,%
被视为换行符,除非它被转义。因为我们需要一个文字 %
,所以在上面的命令中用反斜杠转义了
有关其工作原理的更多信息,请参阅 man 5 crontab
。
备选
正如 twalberg 所指出的,同样的逻辑反过来也适用。我们可以 运行 每个星期一的 cronjob,然后测试那个星期一是否是该月的前 7 天之一:
2 1 * * Mon test $(date +\%e) -le 7 && path/to/my/script.sh
如果您使用 Debian 或 Debian 衍生产品附带的 cron,您可以使用:
0 0 */50,1-7 * MON path/to/my/script.sh
是的,它有效,但有点难以解释为什么。
首先,让我们考虑这个表达式:
0 0 1-7 * MON path/to/my/script.sh
这个将 运行 在日期 1-7 以及每周一举行。这几乎就是我们想要的,除了我们想要 day-of-month 和 day-of-week 字段之间的“AND”关系,而不是“OR”关系。
奇怪的额外 */50
位利用了 Debian cron 的表达式解析逻辑中的一个怪癖。它使 cron 认为 day-of-month 字段是通配符字段,并应用“AND”逻辑。
注意 – 这是一个 hack。如果您使用此表达式,请确保将其记录下来以避免以后混淆。