Cron

Cron 是什么?

cron 是类Unix计算机系统上的一种用于执行定时任务的软件工具。

crontab 是什么?

crontab 是linux操作系统中的命令,用于管理系统中定时任务。同时/etc/crontab配置文件用于存储定期执行的shell命令。可以运行man crontab查看更多crontab的使用方法。在终端输入命令cat /etc/crontab可以查看crontab文件的格式:

# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │                                   7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * * command to execute
1
2
3
4
5
6
7
8
9

crontab 文件中的每一行代表了一项定时任务,任务的格式如上所示,* * * * * command,以空格作为分割符。如:1 0 * * * printf "" > /var/log/apache/error_log 表示每天00:01定时清空apache中的error_log文件。

非标准预定义的宏

一些cron的实现,支持下面非标准的宏命令:

Entry Description Equivalent to
@yearly (or @annually) Run once a year at midnight of 1 January 0 0 1 1 *
@monthly Run once a month at midnight of the first day of the month 0 0 1 * *
@weekly Run once a week at midnight on Sunday morning 0 0 * * 0
@daily (or @midnight) Run once a day at midnight 0 0 * * *
@hourly Run once an hour at the beginning of the hour 0 * * * *
@reboot Run at startup N/A

cron expression 是什么?

cron expression 是一种用于定义时间/日期的字符格式,以空格作为分隔符,表示一组用于执行日程的规约。

cron expression 语法格式

标准字段

cron expression 语法一般有 5-6 个字段,格式如下:

Field Required Allowed Values Allowed special characters Remartks
Minutes Yes 0–59 * , -
Hours Yes 0–23 * , -
Day of month Yes 1–31 * , - ? L W ? L W only in some implementations
Month Yes 1–12 or JAN–DEC * , -
Day of week Yes 0–6 or SUN–SAT * , - ? L # ? L # only in some implementations
Year No 1970–2099 * , - This field is not supported in standard/default implementations.

MonthDay of week字段中的缩写是不区分大小写的。一些其他使用CRON格式的实现中,会在最前面增加seconds字段,这种情况下CRON表达式由 6-7个字段组成,如下图所示:

cron-syntax

cron 表达式中的特殊字符

  1. 标准字符
  • *(any) :: 在这个域上包含所有合法的值,如:在Month上使用,意味着每个月都会触发任务。
  • -(range) :: 用于指定域上的范围,如:在Hours设置6-10,则意味着6、7、8、9、10 这几个小时都会触发任务。
  • ,(values) :: 用于分割某个域上值列表,如:在Minute设置0,15,30,则意味着0分钟、15分钟、30分钟触发任务。
  1. 非标准字符

在一些其他cron的实现中,如Quartz Java scheduler中,支持一些非标准特殊字符,如下所示:

  • /(increments) :: 用于指定域上值得递增。如:在Minute域上设置*/15表示每15分钟触发任务。
  • ?("未定义值") :: 当需要在两个字段中确定一个字段的值时非常有用,如:在需要在day-of-month触发任务,但又不关心day-of-week,那么day-of-month字段的值为10,day-of-week值为?
  • #(occurrence) :: 字符只能用于day-of-week字段中,用于表示指定月份中第几周的哪儿一天。如设置day-of-week域值为6#3意味着某月的第三个周五。
  • L(last) :: 作用在不同的作用域含义不同。作用在day-of-month表示某月的最后一天,如Month设置为JANDay-of-month设置为L,表示1月的最后一天;作用在day-of-week表示周的最后一天,如:5L表示最后的星期五
  • W(weekday) :: 用于定义day-of-month域中最接近指定天数的工作日(星期一至星期五)。如:day-of-month值为10W,则表示本月中接近第10天的工作日,如果第十天为星期六,则表示任务会在周五触发;如果第十天为星期天,则表示任务会在下周一触发。如果day-of-month值为1W,并且当天为周六,则任务会在下周一进行触发,并不会跳转到前一个月份。W字符只能用于day-of-month字段,并且值的单一的天数,不能与-(range),(values)同时使用。

cron 的不同实现

以上描述,主要为 linuxcrontab文件中cron表达式的规范,除此之外还有一些其他实现,如springQuartz

spring 中 cron 表达式

通过查看CronSequenceGenerator类,spring 支持的crontab格式的语法,来定义周期任务。spring 限定的cron模式为6个字段,分别代表second minute hour day month weekday, monthweekady支持英文简写名称。 范例:

  • "0 0 * * * *" :: 每0分0秒
  • "*/10 * * * * *" :: 每隔10秒
  • "0 0 8-10 * * *" :: 每天8点、9点、10点
  • "0 0 6,19 * * *" :: 每天6点、19点
  • "0 0/30 8-10 * * *" :: 每天8点、8点半、9点、9点半、10点、10点半
  • "0 0 9-17 * * MON-FRI" :: 从星期一到星期五,每天9点到17点
  • "0 0 0 25 12 ?" :: 每年12月25日 0点 0分 0秒

quartz 中 cron 表达式

quartz 中支持6-7个字段,其格式如下:

Field Name Mandatory Allowed Values Allowed Special Characters
Seconds YES 0-59 , - * /
Minutes YES 0-59 , - * /
Hours YES 0-23 , - * /
Day of month YES 1-31 , - * ? / L W
Month YES 1-12 or JAN-DEC , - * /
Day of week YES 1-7 or SUN-SAT , - * ? / L #
Year NO empty, 1970-2099 , - * /

更多quartz cron 表达式细节详见说明文档

一些细节

这里有一些细节需要注意,对于字段day of week的取值范围,不同的实现可能会不同:

  • crontab 为 0-7 or SUN-SAT, 其中 0 或 7 为 SUN, 1-6 为 MON - SAT
  • spring 取值范围同crontab
  • quartz 为 1-7 or SUN-SAT , 其中 1 为 SUN, 2-6 为 MON - SAT

所以在使用 day of week 字段时推荐使用英文简写,避免使用数字,导致不必要的错误,详见Crontab Day of the Week syntax

参考

Last Updated: 5/25/2019, 10:17:23 PM