在每个月的第一个星期一执行cron工作?


32

我想在每个月的第一个星期一从cron到cron工作。cron Wikipedia页面上说

虽然通常在时间/日期指定字段都与当前时间和日期匹配时执行作业,但是有一个例外:如果“月份”和“星期几”都受到限制(而不是“ *”),则可以 “月几”字段(3)或“星期几”字段(5)必须与当前日期匹配。

(我的重点)

这是否意味着我不能每月的第一个星期一,而只能每月的第一个(或任何一天)呢?我想不出办法。


slhck-听起来不错的解决方案-您介意将其扩展为完整代码的答案吗?然后我将其标记为正确:)
Max Williams

Answers:


39

您可以将条件放入实际的crontab命令中:

[ "$(date '+%a')" = "Mon" ] && echo "It's Monday"

现在,如果在一个月的前七个天之一中满足此条件,则您拥有了第一个星期一。请注意,在crontab中,虽然需要转义百分比语法:

0   12  1-7 *   *   [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday"

echo命令替换为要运行的实际命令。我也找到了类似的方法


实际上,slhck,我讲得太早了-这在我的crontab中不起作用:出于某种原因,日期测试似乎有问题。这部作品在命令行[ "$(date '+%a')" = "Mon" ] && echo "It's Monday"一样[ $(date '+%a') = "Mon" ] && echo "It's Monday" 但是,在crontab似乎在这个测试中失败。我也无法从cron那里获得任何有用的反馈:我正在尝试[ "$(date '+%a')" = "Tue" ] >> /home/deploy/cron.log 2>&1将任何错误输出捕获到日志中,但这也不起作用:/
Max Williams

嗯 您可以检查date输出是否正确吗?例如,只需要cron运行一个将其输出到文件的命令即可:date '+%a' > ~/datetest 2>&1–然后检查是否生成了正确的字符串以进行比较。
slhck

1
我发现这个问题-在百分比+%a需要逃跑时,它是在crontab,即是此需要的行: [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday"。如果您可以更新答案,这对以后的读者会有所帮助:)再次感谢
麦克斯

哦,现在我明白了。很高兴它现在可以正常工作,谢谢您的尝试!
slhck

14

我有一台使用西班牙语进行语言环境设置的计算机,因此,此方法对我不起作用,因为星期一更改为lun

其他语言也会失败,因此,我对可接受的答案做了一些细微的改动,以消除语言障碍:

 0 9 1-7 * *   [ "$(date '+\%u')" = "1" ] && echo "¡Es lunes!"

+1¡Muy bien,塞纳尔!
JakeGould

1
Gracias¡普拉维达!; D
cumanacr

这应该是公认的答案。我有一个荷兰语言环境,在工作日也使用不同的名称。与比较字符串来确定星期几相比,使用数字也感觉更干净。
0ne_Up

7

当不需要处理日数时,我发现它更容易。

在每月的第一个星期一运行:

0 2 * * 1 [ `date '+\%m'` == `date '+\%m' -d "1 week ago"` ] || /path/to/command

例如,如果一周前的月份与当前月份不同,那么我们在该月的第一天1(=星期一)。

同样,对于第三个星期五

0 2 * * 6 [ `date '+\%m'` == `date '+\%m' -d "3 weeks ago"` ] || /path/to/command

例如,如果3周前的月份与当前月份不同,则我们位于该月份的第3天6(=星期五)


一周的第六天是星期六而不是星期五。
罗伯特·

4

我已计划将在每月的第4个星期一的下午4:00运行作业,如下所示:

0 16 22-28 * Mon [ "$(date '+\%a')" == "Mon" ] && touch /home/me/FourthMonOfMonth.txt

1

据我所知,不可能仅使用crontab,但是可以使用包装器功能从“一个月的前7天” contab条目中选择正确的日期。从条目中看到这一点

包装脚本将是

#! /usr/bin/ksh
day=$(date +%d)
if ((day <= 7)) ; then
   exec somecommand
fi
exit 1

并且您需要使用crontab条目运行它(假设它被称为wrapper.sh并且全局可用)

0 0 * * 1 wrapper.sh

谢谢elemaki。我想到了一种类似的解决方案,在运行的任务中使用一些额外的代码,让它测试脚本中是否是该月的第一个星期一,然后在crontab中的每个星期一进行调用。这是一个红宝石脚本,因此很容易测试星期几。但是我希望只有一种crontab方式。
马克斯·威廉姆斯

1

在Solaris 10上,我必须将条件格式设置如下:

[ `date +\%a` = "Sat" ] && echo "It's Saturday"

1

您可以尝试在每月的前7天运行cronjob,并使其仅在星期一执行。

30 8 * * 1 [`date +\%d` -le 07] && <job>

以上应该为您工作。


命中率再提高+1,然后运行第一周,检查星期一。:-)
xmedeko

1

我建议使用

"$(/bin/date '+%\w')" = "1"

代替

"$(date '+\%a')" = "Mon"

以避免语言环境问题。


0

我为此类问题提供了一个通用的解决方案,它适用于本月的最后一个工作日的第一,第二,第三.....。

您可以像这样使用它:

30 06 * * Mon run-if-today 1 "Mon" && echo "First Monday"
30 06 * * Thu run-if-today 3 "Thu" && echo "Third Thursday"
30 06 * * Sun run-if-today L "Sun" && echo "Last Sunday"

脚本如果今天运行,则检查工作日和所需的星期日期范围,如果两者都匹配,则返回0,否则返回1。

在此处检查代码。https://github.com/xr09/cron-last-sunday


0

我相信这可以更优雅地解决问题:

30 8 1-7 * 1 /run/your/job.sh

1
h!:“如果两个字段都受限制(即不是*),则当任何一个字段与当前时间匹配时,将运行该命令。”
symcbean 2014年

同样在2月(结束于28日),它不会每4年运行一次。
igraczech '16

“任一个”是指它们中的任何一个,而不是“两者”。该程序将在每月的第7天每天运行。
minusf

该行会在第一次运行一个命令,每个月的第七,以及对每星期一
托马斯的Jakub RUP

0

由于我使用php和js解释cron语句,因此无法使用bash。最后,我发现它实际上可能只用cron的:

0 30 8 * 1/1 MON#1

希望这对其他人有帮助。无论如何,祝大家美好的一天。:-)


这不是cron,可能是石英
sivann

-1
0 9 1-7 * 1 * 

这将在每月的每个星期一工作。


答案已被接受,您的答案是否更好,在新版本中是否有所不同或有用等?
mic84 '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.