【发布时间】:2009-09-05 06:33:25
【问题描述】:
我们想使用 cronjob 来创建数据库备份。
应每两天进行一次备份。可以使用下面的cron-entry吗?
0 0 2 * * * backup-command
如果这是错误的,请告诉我设置 cron 2 天的正确命令。
【问题讨论】:
标签: cron
我们想使用 cronjob 来创建数据库备份。
应每两天进行一次备份。可以使用下面的cron-entry吗?
0 0 2 * * * backup-command
如果这是错误的,请告诉我设置 cron 2 天的正确命令。
【问题讨论】:
标签: cron
来自here:
Cron 还支持 'step' 值。
dom 字段中的
*/2值将 意味着该命令每两天运行一次 同样,*/5在小时字段中 意味着该命令每 5 次运行一次 小时。例如* 12 10-16/2 * * root backup.sh等同于:
* 12 10,12,14,16 * * root backup.sh
所以我想你想要0 0 */2 * *。
您所拥有的 (0 0 2 * *) 将在每月 2 日午夜运行该命令。
附言您的答案似乎有一个额外的星号。格式应为:
minute hour dom month dow user cmd
因此,您的额外星号将位于 user 字段中。这是故意的吗?
【讨论】:
*/2 很清楚,但是10-16/2 是什么意思呢?
免责声明:这是我的deleted 答案here 的副本。我确实相信这个问题更规范,我的回答更适合这里。
这个问题有两种解释方式。
由于一个月有多少天,这是两种完全不同的情况。
为此,我们使用定义范围和步长值的组合:
man 5 crontab: 步长值可以与范围结合使用。在带有/<number>的范围之后指定跳过 范围内的数字值。例如,可以使用0-23/2在“小时”字段中指定每隔一小时执行一次命令 (V7 标准中的替代方案是0,2,4,6,8,10,12,14,16,18,20,22)。也允许步长值 在星号之后,因此如果指定要每两个小时运行一次的作业, 你可以使用*/2。
请参阅以下示例:
# Example of job definition:
# .-------------------- minute (0 - 59)
# | .----------------- hour (0 - 23)
# | | .-------------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
0 0 */2 * * command1
0 0 2-31/2 * * command2
* * */2 * * command3
command1 将在每个奇数日的 00:00 执行(步骤 2 的默认范围,即 1,3,5,7,...,31)command2 将在每个偶数日的 00:00 执行(即 2,4,6,8,...,30)command3 是一个经常犯的错误。这将在每个奇数日的每一分钟运行。注意:应该理解,在这种方法中command1 将在 1 月 31 日和 2 月 1 日(连续 2 天)运行
注意:应该理解,在这种方法中,command2 将跳过 1 月 31 日和 2 月 1 日,并且只会在 3 天后运行。
这里变得更有趣了。上面的注释已经证明了月份有奇数天的问题。
快速思考的方法是评估一年中的哪一天:
% date -d "2018-01-31" '+%j'
031
% date -d "2018-02-01" '+%j'
032
您可以轻松地调查它是奇数还是偶数。但是,这样做时,您在普通年(365 天;闰年有 366 天)的 12 月 31 日和 1 月 1 日再次遇到问题。当您有一个给定日期的连续计数器时,可以解决此问题。输入 UNIX 时间戳,自 1970-01-01 00:00:00 UTC 以来的总秒数。
% date -d "2018-12-31" '+%s %j'
1546214400 365
% date -d "2019-01-01" '+%s %j'
1546300800 001
% date -d "2019-12-31" '+%s %j'
1577750400 365
% date -d "2020-01-01" '+%s %j'
1577836800 001
对于从“2018-03-14”开始每隔一天在00:00 和command5 在00:00 运行command4 的cronjob,crontab 将如下所示:
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
0 0 * * * daytestcmd 2 && command4
0 0 * * * daytestcmd 3 20180314 && command5
daytestcmd 定义为
#!/usr/bin/env bash
# get start time in seconds
start=$(date -d "${2:-@0}" '+%s')
# get current time in seconds
now=$(date '+%s')
# get the amount of days (86400 seconds per day)
days=$(( (now-start) /86400 ))
# set the modulo
modulo=$1
# do the test
(( days >= 0 )) && (( days % modulo == 0))
备注: UNIX 时间以 UTC 表示。如果您的 cron 在受夏令时影响的不同时区运行,建议不要在 2 点到 3 点之间运行命令。这可能会跳过命令或运行命令两次(取决于时间是向前跳还是向后跳)
备注:UNIX时间不受闰秒影响
【讨论】:
daytestcmd 2和daytestcmd 3吗? Shell 函数和脚本不将它们的参数放在括号中。
daytestcmd 中,您可以只使用(( days % modulo == 0 )) 而不是[[ $(( days % modulo )) == 0 ]]。
如果你想使用crontab -e 命令,试试这个时间模式:
0 1 */2 * * command_to_execute
或者,您可以尝试SetCronJob 获取基于网络的解决方案。您可以使用第二个创建行轻松地每 2 天创建一次 cron 作业。
【讨论】: