Linux 定时任务最常用的就是 cron,但写表达式时总会碰到几个经典问题:第 5 段到底是"星期几"还是"星期几(1-7,周日为 1)"?0 0 * * 0 和 0 0 * * 7 有区别吗?Quartz 的 cron 比 Linux 多两段,第 6 段到底是"年"还是"秒"?
这篇文章把 cron 表达式的 6 段语法讲透,配合在线解析工具把抽象的表达式变成可读的"什么时候执行"说明,解决"看懂已有表达式"和"写出正确表达式"两个高频痛点。
基本语法(Linux cron 5 段)
* * * * * command
│ │ │ │ │
│ │ │ │ └── 星期几(0-7,0 和 7 都是周日)
│ │ │ └──── 月份(1-12)
│ │ └────── 日期(1-31)
│ └──────── 小时(0-23)
└────────── 分钟(0-59)
Quartz 扩展为 6 段,前面多一个 秒(注意 Spring 的 @Scheduled 虽然也是 6 段,但周字段仍按 0-7、0 和 7 为周日,与本图不同):
* * * * * *
│ │ │ │ │ │
│ │ │ │ │ └── 星期几(1-7,周日为 1)
│ │ │ │ └──── 月份(1-12)
│ │ │ └────── 日期(1-31)
│ │ └──────── 小时(0-23)
│ └────────── 分钟(0-59)
└──────────── 秒(0-59)
核心陷阱:0 0 * * 0 vs 0 0 * * 7
Linux cron 中,星期几字段 0 和 7 都是周日——最初 cron 只认 0,后续实现为兼容旧写法又接受了 7,所以 0-7 都合法,两个表达式在 Linux 上行为一致。
# 这两条在 Linux 上等价:每周日零点执行
0 0 * * 0 cleanup.sh
0 0 * * 7 cleanup.sh
关键坑:Spring 的 @Scheduled 也是 6 段(秒在前),但周字段规则和 Linux 完全一致——取值 0-7,0 和 7 都是周日,1 是周一,所以 Linux 的 0 0 * * 1 在 Spring 里写成 0 0 0 * * 1,仍是每周一。真正相反的是 Quartz:周字段是 1-7,1 表示周日、7 表示周六,而且「日」和「周」两个字段必须有一个写成 ?。所以同一组数字搬到 Quartz 写成 0 0 0 ? * 1,含义就变成每周日——看着只多了一个秒字段,执行时间却差了一天。
每段支持的特殊字符
| 字符 | 含义 | 示例 | 说明 |
|---|---|---|---|
* |
任意值 | * * * * * |
每分钟执行 |
, |
枚举 | 1,3,5 * * * * |
每小时的第 1/3/5 分钟执行 |
- |
范围 | 0-30 * * * * |
每小时前 30 分钟每分钟 |
/ |
步长 | */5 * * * * |
每 5 分钟(0,5,10,15...) |
? |
忽略(仅 Quartz) | 0 0 0 * * ? |
「日」和「周」必须有且只有一个写成 ? |
L |
最后(仅日期/星期) | 0 0 0 L * ? |
每月最后一天零点 |
W |
工作日(仅日期) | 0 0 0 15W * ? |
离每月 15 号最近的工作日 |
最容易写错的:*/5 不是"每 5 分钟",而是"从 0 开始,每隔 5 分钟"——*/5 * * * * 和 0-59/5 * * * * 等价,都是 0,5,10...55。但 3/5 * * * * 是 3,8,13...58。
用在线解析工具验证
光靠脑子想很容易搞错,把表达式粘进 Cron 表达式在线解析 工具:
- 手动切换 Linux 5 段 / Spring 6 段 / Quartz 6-7 段,选对模式才不会把段数和周字段读错
- 常用示例按钮跟着模式变:Linux 用 5 段、Spring 补秒字段、Quartz 再用
?占位并把周字段按 1 = 周日 重算,点一下就是该模式下的正确写法 - 解析后显示"执行计划预览"——未来 5 次执行时间,一眼看出
0 0 * * 0是不是周日 - 对可疑的表达式(比如日期和星期同时指定、用了
7作周日、Quartz 里写0当周日)给出黄色警告 - 切换模式后警告会跟着变,同一条表达式在三种框架下的合法性一次看清
常见坑
- "日期 + 星期"同时指定:
0 0 1 * 1在 Linux 上是"每月 1 号 或 周一"(OR 关系),很多人以为是 AND。Quartz 里必须用?放弃其中一个。 - 月份字段从 1 开始还是 0:月份永远是 1-12,不要和 Java 的
Calendar.MONTH(0-11)搞混。 */1和*不一样吗:执行结果完全一样,但*/1可读性差,建议直接写*。- 秒级调度:Linux cron 最小粒度是分钟,需要秒级请用 Quartz。
相关工具与速查
- Cron 表达式在线解析:选择 Linux / Spring / Quartz 模式后解析,展示执行计划预览和可疑警告
- crontab 命令速查:Linux / macOS 的 crontab -l / -e / -r / 日志查看 / SELinux 权限等高频命令