Skip to content

Cron 表达式详解与实战 ​

Cron 表达式是一种用于描述周期性执行时间的字符串,广泛应用于各种任务调度框架(如 Linux Crontab、Quartz、Hangfire、Spring Task 等)。通过简短的字符组合,它可以精确表达诸如“每周五下午两点”、“朝九晚五每半小时”等复杂的业务定时需求。

一、 语法结构 ​

Cron 表达式通常以 5 到 7 个空格隔开,分为 6 或 7 个域。常见的两种标准格式:

  1. 六位标准(常见于多数现代调度框架,如 .NET Core / Spring): 秒 分 小时 日期 月份 星期
  2. 七位标准(包含年份): 秒 分 小时 日期 月份 星期 年份

各字段的允许值与特殊字符:

字段允许值允许的特殊字符
秒 (Seconds)0~59 的整数, - * /
分 (Minutes)0~59 的整数, - * /
小时 (Hours)0~23 的整数, - * /
日期 (DayofMonth)1~31 的整数(需考虑当月天数), - * ? / L W C
月份 (Month)1~12 或 JAN-DEC, - * /
星期 (DayofWeek)1~7 或 SUN-SAT(1=SUN), - * ? / L C #
年 (Year) [可选]1970~2099, - * /

二、 特殊字符图解 ​

理解 Cron 的关键在于掌握以下特殊字符的用法:

  • * (所有值):表示匹配该域的任意值。例如在“分”域使用 *,表示每分钟触发。
  • ? (不指定值):只能用于“日期”和“星期”域。因为日期和星期会相互影响,如果只关心某一个,另一个必须用 ? 占位。例如“每月20号触发”,星期域必须填 ?。
  • - (区间):表示一个范围。例如在“分”域使用 5-20,表示第 5 到第 20 分钟内每分钟触发。
  • / (增量):表示起始时间开始触发,然后每隔固定时间触发一次。例如在“分”域使用 5/20,表示从第 5 分钟开始,每 20 分钟触发一次(即 5, 25, 45 分钟)。
  • , (枚举):表示列出具体值。例如在“分”域使用 5,20,表示在第 5 分和第 20 分触发。
  • L (最后 Last):只能用于“日期”和“星期”域。
    • 在“日期”域:表示本月最后一天。
    • 在“星期”域:表示本周最后一天(即周六 SAT)。如果在数字后跟 L,如 6L,表示本月最后一个星期五(1=SUN, 6=FRI)。
  • W (工作日 Weekday):只能用于“日期”域。表示离指定日期最近的有效工作日(周一至周五)。如 5W,如果 5 号是周六,则在最近的周五(4号)触发;如果是周日,则在周一(6号)触发。注意:寻找最近工作日不会跨月。
  • LW (最后工作日):连用表示某个月的最后一个工作日。
  • # (第几个星期几):只能用于“星期”域。格式为 星期#第几个。例如 4#2 表示某月的第二个星期三(4=WED)。

三、 常见实战场景速查 ​

1. 简单周期循环 ​

  • 0 * 14 * * ? 每天下午 2:00 到 2:59 期间的每 1 分钟触发
  • 0 0/5 14 * * ? 每天下午 2:00 到 2:55 期间的每 5 分钟触发
  • 0 0 12 * * ? 每天中午 12:00 触发
  • 0 15 10 * * ? 每天上午 10:15 触发

2. 工作时间场景 ​

  • 0 0 10,14,16 * * ? 每天上午 10:00、下午 2:00、下午 4:00 触发
  • 0 0/30 9-17 * * ? 朝九晚五工作时间内,每半小时触发
  • 0 15 10 ? * MON-FRI周一到周五每天上午 10:15 触发

3. 月度与月末场景 ​

  • 0 0 2 1 * ? 每月的 1 日凌晨 2:00 触发
  • 0 15 10 15 * ? 每月 15 日上午 10:15 触发
  • 0 15 10 L * ? 每月最后一日的上午 10:15 触发
  • 0 15 10 ? * 6L 每月的最后一个星期五上午 10:15 触发
  • 0 15 10 ? * 6#3 每月的第三个星期五上午 10:15 触发

四、 避坑指南 ​

  1. 区分 5 位和 6 位表达式
    • Linux 系统的 Crontab 默认是 5 位(分 时 日 月 周),不支持秒。
    • 大多数业务代码框架(如 Quartz、.NET Core 定时库)支持 6 位或 7 位,开头第一位是秒。
    • 复制网上的表达式前,一定要先确认你使用的框架支持几位。
  2. ? 和 * 在日期/星期上的冲突 如果指定了具体的日期(如每月 1 号),星期必须用 ?(如 0 0 0 1 * ?)。如果星期用 *,会被框架判定为语法错误或导致不可预期的多次触发。
  3. 星期 1 是周日 在标准的 Cron 表达式中,1 = SUN,2 = MON,依次类推直到 7 = SAT。容易因为习惯把 1 当作周一导致调度错乱。

方舟 · Ark