Cron 表达式详解:从入门到实战
Cron 表达式详解:从入门到实战
Cron 表达式是 Unix 系统中用于配置定时任务的核心机制。无论是服务器运维、数据备份、日志轮转还是 CI/CD 流水线调度,Cron 都扮演着不可或缺的角色。然而,Cron 表达式的语法常常让人困惑——一串看似随机的数字和符号,背后却有着清晰的逻辑。本文将系统性地拆解 Cron 表达式的每个组成部分,帮助你从入门到实战全面掌握。
一、5 字段格式详解
标准 Cron 表达式由 5 个字段组成,按顺序分别是:
┌──────── 分钟 (0-59)
│ ┌────── 小时 (0-23)
│ │ ┌──── 日 (1-31)
│ │ │ ┌── 月 (1-12)
│ │ │ │ ┌ 星期 (0-6,0=周日)
│ │ │ │ │
* * * * *
每个字段的取值范围:
| 字段 | 含义 | 取值范围 | 说明 |
|---|---|---|---|
| 第 1 字段 | 分钟 | 0-59 | 每小时的第几分钟 |
| 第 2 字段 | 小时 | 0-23 | 每天的第几小时(24 小时制) |
| 第 3 字段 | 日 | 1-31 | 每月的第几天 |
| 第 4 字段 | 月 | 1-12 | 也可以用 JAN-DEC |
| 第 5 字段 | 星期 | 0-6 | 0=周日,也可以用 SUN-SAT |
注意:部分实现(如 Spring、Quartz)支持 6 或 7 字段格式,在 5 字段前增加了”秒”字段,末尾增加”年”字段。本文以标准 5 字段为主。
二、特殊字符详解
Cron 表达式的强大之处在于其特殊字符,它们赋予了表达式灵活的时间匹配能力。
2.1 星号 *——匹配所有值
* 表示该字段匹配所有可能的值:
* * * * * # 每分钟执行
0 * * * * # 每小时的第 0 分钟执行
2.2 斜杠 /——步长值
/ 用于指定间隔步长:
*/5 * * * * # 每 5 分钟执行(0, 5, 10, 15, ...)
0 */2 * * * # 每 2 小时执行(0:00, 2:00, 4:00, ...)
0 0 */3 * * # 每 3 天的午夜执行
/ 也可以指定起始值:
10/5 * * * * # 从第 10 分钟开始,每 5 分钟执行(10, 15, 20, ...)
2.3 连字符 -——范围
- 指定一个连续的范围:
0 9-17 * * * # 工作时间(9 点到 17 点)每小时执行
0 0 1-7 * * # 每月 1-7 日的午夜执行
2.4 逗号 ,——枚举
, 列出多个离散的值:
0 8,12,18 * * * # 每天 8 点、12 点、18 点执行
0 0 * 1,4,7,10 * # 每季度首月的午夜执行
2.5 特殊字符组合
这些字符可以组合使用,实现更复杂的调度:
0 9-17 * * 1-5 # 工作日工作时间每小时执行
*/15 8-18 * * 1-5 # 工作日 8-18 点每 15 分钟执行
0 0 1,15 * * # 每月 1 号和 15 号午夜执行
2.6 问号 ?——日或星期的”不指定”
部分实现中(如 Quartz),? 用于日或星期字段,表示”不指定值”。当日和星期字段同时有具体值时可能产生冲突,用 ? 可以避免:
0 0 12 * * ? # 每天中午 12 点(星期字段用 ? 忽略)
0 0 12 ? * MON # 每周一中午 12 点(日字段用 ? 忽略)
三、常用示例
3.1 基础调度
* * * * * # 每分钟
*/5 * * * * # 每 5 分钟
0 * * * * # 每小时整点
0 0 * * * # 每天午夜
0 0 * * 0 # 每周日午夜
0 0 1 * * # 每月 1 号午夜
0 0 1 1 * # 每年 1 月 1 日午夜
3.2 工作日调度
0 9 * * 1-5 # 工作日每天早上 9 点
0 9,18 * * 1-5 # 工作日早 9 点和晚 6 点
30 8 * * 1 # 每周一早上 8:30
3.3 运维场景
0 2 * * * # 每天凌晨 2 点(适合数据库备份)
0 */6 * * * # 每 6 小时(适合日志轮转)
0 0 * * 6 # 每周六午夜(适合周报生成)
0 0 1 */3 * # 每季度首月 1 号(适合季度报告)
30 4 * * 0 # 每周日凌晨 4:30(适合系统维护)
3.4 监控与健康检查
*/1 * * * * # 每分钟检查服务状态
*/5 * * * * # 每 5 分钟检查磁盘空间
0 8 * * 1-5 # 工作日早 8 点发送日报
四、调试技巧
4.1 理解执行时间
Cron 的调度基于系统时区。调试时首先确认:
- 系统时区:
timedatectl或date查看 - Cron 守护进程时区:部分系统使用独立时区配置
- 夏令时影响:Cron 不感知夏令时,可能导致调度偏移
4.2 常见陷阱
-
日和星期的 OR 逻辑:同时指定日和星期时,两个条件取 OR(满足任一即执行),而非 AND
# 错误理解:每月 1 号且为周一 # 实际行为:每月 1 号 或 周一 0 0 1 * 1 -
月末日问题:
0 0 31 * *在没有 31 号的月份不会执行 -
步长与范围交互:
1-30/5表示从 1 到 30 每隔 5 执行(1, 6, 11, 16, 21, 26) -
环境变量缺失:Cron 环境的 PATH 通常很精简,脚本中应使用完整路径
4.3 验证表达式
手动推算 Cron 执行时间既费时又容易出错。推荐使用 CodeKit Cron 解析器 在线验证表达式,它可以:
- 解析表达式含义为自然语言描述
- 列出接下来的执行时间点
- 高亮显示语法错误
- 支持多种 Cron 方言(标准 5 字段、Quartz 7 字段等)
4.4 日志与排查
在 crontab 中添加日志输出有助于排查问题:
# 将输出和错误都记录到日志
0 2 * * * /path/to/backup.sh >> /var/log/backup.log 2>&1
# 使用 MAILTO 接收错误通知
MAILTO=admin@example.com
0 2 * * * /path/to/backup.sh
五、不同实现的差异
| 特性 | 标准 Cron | Quartz | Spring | GitHub Actions |
|---|---|---|---|---|
| 字段数 | 5 | 6-7 | 6 | 5 |
| 秒支持 | ❌ | ✅ | ✅ | ❌ |
? 支持 | ❌ | ✅ | ✅ | ❌ |
L(最后) | ❌ | ✅ | ✅ | ❌ |
W(工作日) | ❌ | ✅ | ✅ | ❌ |
#(第 N 个星期X) | ❌ | ✅ | ✅ | ❌ |
使用前务必确认目标平台支持的语法特性。
总结
Cron 表达式虽然初看晦涩,但其核心逻辑非常清晰:5 个字段、4 种特殊字符、组合即得。掌握 *、/、-、, 四个特殊字符的用法,就能覆盖绝大多数调度需求。调试时注意时区、日与星期的 OR 逻辑以及环境变量问题,善用在线解析工具验证表达式。无论你是运维工程师还是后端开发者,精通 Cron 表达式都是一项必备技能。