由于 cron 不支持对该要求进行简单、直接的转换,因此我会使用时间戳文件和每日 cron 作业来处理它:
0 0 * * * /path/to/wrapper/script/below.sh
Run Code Online (Sandbox Code Playgroud)
包装脚本:
#!/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
Run Code Online (Sandbox Code Playgroud)
这有几个风险:
根据stackoverflow 上的这个答案,您可以使用以下语法来完成此操作:
00 12 * * * test $(( $(date +\%s)/24/60/60\%45 )) = 20 && your_script
Run Code Online (Sandbox Code Playgroud)
这项工作每天中午都会运行。然后,它计算从纪元开始的天数的模数,并测试它是否等于您指定的模数。在本例中,我指定了 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
Run Code Online (Sandbox Code Playgroud)
(请注意,如果您不在 UTC 时区,则可能需要考虑一天中的时间)。
如果您不需要正好 45 天,但“一个半月”就可以了,那么一个简单的方法是每三个月在月初运行,并在每个月之后的下个月中旬运行那些:
0 12 1 1,4,7,10 * /path/to/script
0 12 16 2,5,8,11 * /path/to/script
Run Code Online (Sandbox Code Playgroud)
对于一般的任意间隔,其他答案显然更好,但 45 天听起来像是基于一个月的长度。人类用户也可能更习惯于一个月的开始或月中发生的事情,而不是每次看到确切的日期漂移一两天。