Cron 表达式与 Crontab 表达式详解
Cron 表达式与 Crontab 表达式详解
引言
在开发定时任务时,我们经常接触到 Cron 表达式。然而,不同框架或系统中使用的 Cron 表达式格式并不统一——有 5 位、6 位甚至 7 位的写法,容易造成混淆。
更严重的是,如果表达式书写错误,可能导致:
- 定时任务从未执行
- 定时任务执行过于频繁
实际上,这里所说的 “Cron 表达式” 是一个广义概念,主要包括两类:
- 狭义的 Cron 表达式(常用于 Java 框架如 Quartz、Spring)
- Crontab 表达式(Unix/Linux 系统原生命令)
本文将系统梳理两者的语法、字段含义、特殊字符及使用示例。
一、Cron 表达式(6 位或 7 位)
1. 基本格式
Cron 表达式是一个字符串,由 5 或 6 个空格 分隔成 6 或 7 个域,每个域代表一个时间单位。
支持两种语法格式:
| 格式 | 字段顺序 |
|---|---|
| 6 位(常用) | Seconds Minutes Hours DayOfMonth Month DayOfWeek |
| 7 位(含年份) | Seconds Minutes Hours DayOfMonth Month DayOfWeek Year |
⚠️ 注意:“秒” 是 Java 生态(如 Spring、Quartz)特有的扩展,标准 Unix crontab 不包含秒。
2. 各字段允许的取值与特殊字符
| 字段 | 允许值 | 特殊字符 | 说明 |
|---|---|---|---|
| 秒 (Seconds) | 0–59 |
- * / |
— |
| 分 (Minutes) | 0–59 |
- * / , |
— |
| 小时 (Hours) | 0–23 |
- * / , |
— |
| 日期 (Day of Month) | 1–31 |
- * ? / L W C |
与星期互斥 |
| 月份 (Month) | 1–12 或 JAN–DEC |
- * / , |
— |
| 星期 (Day of Week) | 1–7 或 SUN–SAT (1=周日, 2=周一, …, 7=周六) |
- * ? / L C # |
与日期互斥 |
| 年 (Year) [可选] | 1970–2099 |
, - * / |
通常省略 |
3. 特殊字符含义
| 字符 | 含义 | 示例 |
|---|---|---|
* |
匹配该域任意值 | * 在分钟域 → 每分钟 |
? |
仅用于日期或星期,表示“不指定”,用于解决两者互斥问题 | 0 0 0 20 * ?:每月 20 号触发,不管星期几 |
- |
范围 | 5-20 在分钟域 → 5 到 20 分每分钟 |
/ |
步长(从起始值开始,每隔 N 单位) | 5/20 → 第 5 分,之后每 20 分(5, 25, 45…) |
, |
枚举多个值 | 5,20 → 5 分和 20 分 |
L |
“Last”,最后一天或最后一个星期几 (仅用于日期或星期) | L 在日期 → 月末最后一天 5L 在星期 → 最后一个星期四 |
W |
“Workday”,最近的有效工作日(周一至周五) (仅用于日期) | 15W → 若 15 号是周六,则在 14 号(周五)执行;若为周日,则在 16 号(周一)执行 |
LW |
组合使用 → 某月最后一个工作日(即最后一个星期五) | LW → 最后一个周五 |
# |
“第几个星期几” (仅用于星期) | 4#2 → 某月第二个星期三(4=周三,2=第二个) |
C |
“Calendar”,仅当日历中该日期存在时才触发 (仅用于日期) | 较少使用 |
💡 关键规则:
日期(DayOfMonth)和星期(DayOfWeek)不能同时指定具体值,必须有一个用?。
4. 常见示例
| 表达式 | 含义 |
|---|---|
*/5 * * * * ? |
每 5 秒执行一次 |
0 */1 * * * ? |
每 1 分钟执行一次 |
0 0 2 1 * ? |
每月 1 日凌晨 2 点执行 |
0 15 10 ? * MON-FRI |
周一至周五上午 10:15 执行 |
0 0 23 * * ? |
每天 23:00 执行 |
0 0 1 * * ? |
每天凌晨 1 点执行 |
0 0 1 1 * ? |
每年 1 月 1 日凌晨 1 点执行 |
0 0 23 L * ? |
每月最后一天 23:00 执行 |
0 0 1 ? * L |
每周日(星期天)凌晨 1 点执行 |
0 26,29,33 * * * ? |
在 26、29、33 分各执行一次 |
0 0 10,14,16 * * ? |
每天 10、14、16 点执行 |
0 0/30 9-17 * * ? |
工作日 9–17 点间每 30 分钟执行 |
0 0 12 ? * WED |
每周三中午 12 点执行 |
0 15 10 ? * 6L |
每月最后一个星期五 10:15 执行 |
0 15 10 ? * 6#3 |
每月第三个星期五 10:15 执行 |
0 15 10 ? * * 2005 |
2005 年每天 10:15 执行 |
✅ 提示:在 Spring Boot 中,若未显式指定年份,表达式通常为 6 位;Quartz 支持 7 位。
二、Crontab 表达式(5 位)
1. 基本介绍
crontab 是 Unix/Linux 系统中用于设置周期性任务的命令。其守护进程 crond 每分钟检查一次是否有任务需要执行。
2. 格式
1 | # 分 时 日 月 周 命令 |
| 字段 | 含义 | 取值范围 |
|---|---|---|
m |
分钟 | 0–59 |
h |
小时 | 0–23 |
dom |
日期(日) | 1–31 |
mon |
月份 | 1–12 或 JAN–DEC |
dow |
星期 | 0–7(0 和 7 都表示星期日)或 SUN–SAT |
⚠️ 注意:
- 没有“秒”字段
- 日期(dom)和星期(dow)可以同时指定,此时满足任一条件即触发(逻辑 OR)
3. 常见示例
| 表达式 | 含义 |
|---|---|
30 16 * * * /path/restart.sh |
每天 16:30 执行 |
40 3 3,15,23 * * /path/restart.sh |
每月 3、15、23 日 3:40 执行 |
30 3 * * 6,0 /path/restart.sh |
每周六、周日 3:30 执行 |
0,30 20-22 * * * /path/restart.sh |
每天 20:00–22:00 之间每 30 分钟执行 |
0 23 * * 6 /path/restart.sh |
每周六 23:00 执行 |
0 */2 * * * /path/restart.sh |
每 2 小时执行一次(0,2,4,…) |
0 11 5 * mon-wed /path/restart.sh |
每月 5 号 且 是周一到周三时,在 11:00 执行 |
0 5 1 jan * /path/restart.sh |
每年 1 月 1 日 5:00 执行 |
💡 注意:
mon-wed是 crontab 支持的缩写,等价于1-3。
三、Cron vs Crontab 关键区别总结
| 特性 | Cron 表达式(Java) | Crontab(Linux) |
|---|---|---|
| 字段数 | 6 或 7 位(含秒) | 5 位(无秒) |
| 秒字段 | ✅ 支持 | ❌ 不支持 |
| 日期 & 星期关系 | 互斥(必须一个为 ?) |
可同时指定(OR 关系) |
| 星期起始 | 1 = 周日 | 0/7 = 周日 |
| 典型使用场景 | Spring、Quartz、XXL-JOB | Linux 系统定时任务 |
四、最佳实践建议
- 明确使用环境:
- Web 应用 → 用 6 位 Cron 表达式(含秒)
- 服务器脚本 → 用 5 位 Crontab
- 避免歧义写法:
- 不要混用
*和具体值在日期/星期上 - 使用
?明确表示“不关心”
- 不要混用
- 测试表达式:
- 使用在线工具验证(如 cron.qqe2.com 或 IDE 插件)
- 注释说明:
- 在代码或 crontab 文件中添加注释,说明触发逻辑
📌 记住:
“能跑 ≠ 正确” —— 务必确认定时任务的触发频率是否符合业务预期!



