如何安排每 45 天执行一次 cronjob?

如何安排每 45 天执行一次 cronjob?

如何通过 cronjob 每 45 天执行一次 shell 脚本?

答案1

如果您不需要正好 45 天,但“一个半月”就可以,那么一个简单的方法是每三个月在月初运行一次,并在每个月之后的下个月中旬运行一次。那些:

0 12  1 1,4,7,10  * /path/to/script
0 12 16 2,5,8,11  * /path/to/script

对于一般的任意间隔,其他答案显然更好,但 45 天听起来无论如何都是基于一个月的长度。人类用户也可能更习惯于月初或月中发生的事情,而不是每次都看到确切的日期漂移一两天。

答案2

由于 cron 不支持对该要求进行简单、直接的转换,因此我将使用时间戳文件和每日 cron 作业来处理它:

0 0 * * * /path/to/wrapper/script/below.sh

包装脚本:

#!/bin/bash
timestampfile=/var/run/this-job/timetampfile

# exit now if it hasn't been 45 days
(( 
  $(date +%s) - $(stat -c %Z "$timestampfile") 
            < 
  (45 * 24 * 60 * 60) 
)) && exit 0

touch "$timestampfile"
: run real script here

这会带来几个风险:

  • 有人删除时间戳文件
  • 有人触摸时间戳文件(无论好坏)
  • 从 cron 作业条目中不明显看出实际脚本每 45 天运行一次

答案3

基于这个关于堆栈溢出的答案,您可以使用以下语法来完成此操作:

00 12 * * *  test $(( $(date +\%s)/24/60/60\%45 )) = 20 && your_script

这项工作每天中午都会运行。然后,它计算从纪元开始的天数的模数,并测试它是否等于您指定的模数。在本例中,我指定了 20,这将使其在今天(2018-05-09 在 00:00 GMT 和 23:59 GMT 之间)评估为 true,然后从今天起 45 天,依此类推。您可以使用以下方法计算/测试下列的:

$ echo $(( $(date +%s)/24/60/60%45 ))
20
$ echo $(( $(date -d '+45 days' +%s)/24/60/60%45 ))
20
$ echo $(( $(date -d '+44 days' +%s)/24/60/60%45 ))
19

(请注意,如果您不在 UTC 时区,则可能需要考虑一天中的时间)。

答案4

crl我在尝试发布使用时遇到了类似的问题OpenBSD 6.6。使用以下脚本来安排下次启动的第一件事。

#!/bin/sh

# copy current crontab to file without launching script    
/usr/bin/crontab -l | grep -v "/var/publishCRL.sh" > /var/tmpCron

# add entry for 45 days from now
# 45 days = 3888000 seconds
/bin/echo $(date -j -r `expr $(date +%s) + 3888000` "+%M %H %d %m")" * /var/publishCRL.sh" >> /var/tmpCron

# load edited crontab
/usr/bin/crontab /var/tmpCron

# cleanup
/bin/rm /var/tmpCron

# do CRL stuff

相关内容