【发布时间】:2011-05-31 18:37:52
【问题描述】:
是否可以每三天运行一次cronjob?或者每月 10 次。
【问题讨论】:
-
是的,这是可能的,这属于超级用户。
-
无论月份界限如何,每 3 天运行一次,可以使用 anacron 完成。
标签: cron
是否可以每三天运行一次cronjob?或者每月 10 次。
【问题讨论】:
标签: cron
每三天运行一次...
0 0 */3 * *
怎么样?
如果您希望它在每月的特定日期运行,例如 1 日、4 日、7 日等...那么您可以在脚本中添加一个条件来检查当月的当前日期。
if (((date('j') - 1) % 3))
exit();
或者,正如@mario 指出的那样,您可以使用 date('k') 来获取一年中的哪一天,而不是根据月份中的哪一天来获取。
【讨论】:
0 0 */3 * * 表示在 1 日、4 日、7 日等运行(*/3 表示 1-31/3 表示 1,4,7...31),因此月底差距会更小。 (如果上个月有 31 天,它将连续运行 2 天。)date('j') % 3 有一个类似的问题,该模式每年都会重新启动,并且年份没有可被 3 整除的天数。
* * */3 * * that says, every minute of every hour on every three days.
0 0 */3 * * says at 00:00 (midnight) every three days.
【讨论】:
因为 cron 是“无状态的”,它不能准确地表达“频率”,只能表达它(显然)与当前时间连续匹配的“模式”。
改写您的问题会使这一点更加明显:“是否可以在每晚 00:01 运行 cronjob,除了在 2 晚内运行的跳过之夜?”当 cron 将当前时间与作业请求时间模式进行比较时,cron 无法知道它是否在过去运行过您的作业。
(当然可以编写一个有状态的 cron 来记录过去的作业,因此包括用于匹配该状态的模式,但这不是大多数操作系统中包含的标准 cron。这样的系统会因为需要引入这种模式何时“重置”的概念。例如,当时间更改时模式是否会重置(即 crontab 条目被修改)?看看你最喜欢的日历应用程序,看看它可以有多复杂来表达计划的重复模式事件,并注意它们没有重置问题,因为开始日历事件有一个自然的“开始”a/k/a“重置”日期。尝试重新安排每隔一周的循环日历事件以推迟一周, 例如在圣诞节。通常你必须终止该重复事件并重新启动一个全新的事件;这说明了即使是复杂的日历应用程序如何表示重复模式的表达能力有限。当然还有日历 h有很多状态——每个单独的事件都可以被删除或独立重新安排[在大多数日历应用程序中])。
此外,您可能希望每 3 晚完成一次工作如果成功,但如果最后一次失败,请立即重试,可能在第二天晚上(不要再等 3 天)甚至更快,比如一个小时后(但在早上到来时停止重试)。显然,cron 不可能知道您的工作是否成功,并且该模式也无法表达替代的更频繁的“重试”计划。
无论如何-- 你可以自己做你想做的事。编写一个脚本,告诉 cron 每晚在上午 00:01 运行它。该脚本可以检查记录“上次运行”的某事*的时间戳,如果是 >3 天前**,则执行该作业并重置“上次运行”时间戳。
(*那个带时间戳的指标是一种持久化状态,您可以对其进行操作和检查,但 cron 不能)
**如果您使用人类可读的时钟时间,请注意时间算术 - 一年两次,有些日子一天有 23 或 25 小时,而 02:00-02:59 在一天内出现两次或者根本没有。使用 UTC 来避免这种情况。
【讨论】:
【讨论】:
then at 2019-02-28 00:00:00 then at 2019-03-01 00:00:00
我不认为你有你需要的东西:
0 0 */3 * * ## <<< WARNING!!! CAUSES UNEVEN INTERVALS AT END OF MONTH!!
不幸的是,*/3 将间隔设置为每月的每一天,不是每 n 天。请参阅:explanation here。在月底,保证会定期出现问题。
1st at 2019-02-01 00:00:00
then at 2019-02-04 00:00:00 << 3 days, etc. OK
then at 2019-02-07 00:00:00
...
then at 2019-02-25 00:00:00
then at 2019-02-28 00:00:00
then at 2019-03-01 00:00:00 << 1 day WRONG
then at 2019-03-04 00:00:00
...
根据this article,您需要在正在执行的命令中添加一些模数学以获得“每 N 天”的 TRUE。例如:
0 0 * * * bash -c '(( $(date +\%s) / 86400 \% 3 == 0 )) && runmyjob.sh'
在此示例中,作业将在每天上午 12:00 进行检查,但仅在自 01-01-1970 以 3 为模的天数为 0 时才会执行。
如果您希望从特定日期开始每 3 天发送一次,请使用以下格式:
0 0 * * * bash -c '(( $(date +\%s -d "2019-01-01") / 86400 \% 3 == 0 )) && runmyjob.sh'
【讨论】:
0 0 1-30/3 * *
这将从 1 日开始每三天运行一次。这是 20 次预定运行 -
【讨论】:
怎么样:
00 00 * * * every 3 days && echo test
every 是一个脚本:
#!/bin/sh
case $2 in
days)
expr `date +%j` % $1 = 0 > /dev/null
;;
weeks)
expr `date +%V` % $1 = 0 > /dev/null
;;
months)
expr `date +%m` % $1 = 0 > /dev/null
;;
esac
所以它每天都在运行。
使用*/3 在每月的 3 号、6 号、... 27 号、30 号运行,但在一个月有第 31 天之后就出错了。 every 脚本只有在年底之后才会出错。
【讨论】:
如果您将其配置为仅运行例如,它会更简单。在星期一和星期四,这将给它提供 3 和 4 天的休息时间。
否则将其配置为每天运行,但让您的 php cron 脚本提前退出:
if (! (date("z") % 3)) {
exit;
}
【讨论】:
由于 UTC 天数正好是 86400 秒(所有天数,忘记闰秒,它们不会影响 UTC 天数),将(整数除法)纪元时间(以秒为单位)除以 86400 得到(完整)经过的天数自纪元。通过更多的数学运算,我们可能会到达这条 cron 行:
12 21 * * * [ $(( ($(date +\%s)/86400+0) \% 3 )) = 0 ] && do_stuff
如果今天是08/30/2021New_York,则执行命令的最佳时间是21:12(或更晚),以确保满天。在这样的时间和日期,命令将被执行。如果需要移动当天,则将0更改为适当的偏移量,以获得当天的0-day。
也可以使用任何其他循环n(而不是 3)。
结果不受月、年或世纪的影响。总会有n天的周期
请注意,cron 要求将 % 转义为 \%。
【讨论】:
如果您希望它在一个月的特定日期运行,例如 1 号、4 号、7 号等...那么您可以在脚本中添加一个条件来检查当月的当前日期。
我认为您需要的只是代替 */3 表示每三天一次,使用 1/3 表示从本月 1 日开始每三天一次。所以 7/3 表示从每月 7 日开始每三天一次,以此类推。
【讨论】:
0 0 * * * [ $(($((date +%-j- 1)) % 3)) == 0 ] && script
从date获取一年中的哪一天,从0开始偏移1,检查是否为模三。
【讨论】:
( 365-1 ) % 3 == 1 但( 1 - 1 ) % 3 == 0?我认为更好的计算将基于自 Unix 纪元以来的天数。
你应该学习crontab的基础知识。
通过命令crontab -e 编辑 cron,然后 ⌃ (CTRL) + X 然后 Y 最后按 ENTER ( return) 在 mac 上保存文件。您可以通过crontab -l检查新的crons是否已安装
一个 crontab 文件有五个字段用于指定分钟、小时、日期 月份、月份和星期几,然后是命令 以该间隔运行。
* * * * * command to be executed
- - - - -
| | | | |
| | | | +----- day of week (0-6) (Sunday=0)
| | | +------- month (1-12)
| | +--------- day of month (1-31)
| +----------- hour (0-23)
+------------- min (0-59)
上面值字段中的* 表示该列的大括号中的所有合法值。
在这里,我写了一篇关于它的详细帖子:Setup Cron in Unix
【讨论】: