Cron 表达式解析器:给非运维同学的入门(2026)
Cron 表达式解析器:给非运维同学的入门
你交付了一个小功能,需要每个工作日早上 9 点跑一次,于是顺手拿起了 cron。三次失败、外加一次生产事故(任务每分钟运行一次,跑了整整一个周末)之后,这已经是你本月第四次在查 cron 表达式语法表。维基百科那一栏表格密密麻麻,StackOverflow 上的回答互相矛盾,AI 助手给你的答案又跟你调度器实际接受的格式对不上。
本文会从第一性原理讲清楚 cron 表达式,面向不每天写它的人——产品经理、创始人、设计师、分析师、以及一年只用几次 cron 的后端开发者。我们会介绍**Ai2Done 的 Cron 解析器**,它能把任何表达式翻译成人话,也能避开那些连资深工程师都会踩的坑。
TL;DR
- 一条 cron 表达式 = 5 个字段:分钟、小时、月份中的某天、月份、星期 —— 空格分隔。
- 最坑的一点:当月份天数(day-of-month)和星期(day-of-week)同时被指定时,经典 Unix cron 把它们当作 OR(任一匹配就触发),这通常并不是你想要的。
- 用 Ai2Done Cron 解析器 在上线前把表达式翻译成人话,看清楚未来 5-10 次触发时间。
- 时区很重要:大多数 cron 调度器跑在 UTC;请在调用方系统(Kubernetes CronJob、AWS EventBridge 等)里显式指定时区。
- 特殊字符
* / , - L W ? #在经典 cron 与 Quartz cron 中含义不同——按你调度器的方言挑用法。
为什么这件事比看起来更难
1975 年的原版 Unix cron 用 5 个字段。现代调度器(Quartz、Kubernetes CronJob、AWS EventBridge、GitLab schedule、GitHub Actions)以互不兼容的方式扩展或修改了这个语法。如今至少有 4 种广泛使用的方言:
- 经典 Unix cron(5 字段,Linux/macOS 的
crontab) - Vixie cron(Linux 上事实标准的实现,带一些扩展)
- Quartz cron(7 字段,包含秒和年,Java 调度器和 AWS EventBridge 都在用)
- Kubernetes CronJob(5 字段,但没有
?,DST 处理略有不同)
在一个系统里跑得完美的表达式,到另一个系统里可能校验失败、在意外时间触发、或干脆永不触发。"这个表达式合法吗?"这个问题,真的取决于方言。
第二个困惑源:"5 个字段"的说法默认你记得顺序。多数工程师在压力下只能想起"有分钟、有小时、再来是日还是月?"正确顺序是 分钟、小时、月份中的某天(day-of-month)、月份、星期(day-of-week)。
第三个困惑源:特殊字符之间的交互很不直观。0 0 1,15 * 1-5 在每月的 1 号和 15 号触发,或者周一到周五(因为经典 cron 对 day-of-month 与 day-of-week 取 OR)。要表达"每月 1 号和 15 号,且必须是工作日",你需要 Quartz cron 的 ? 占位符。
一款好的 cron 解析器会在你部署前,按你的时区显示未来 5-10 次实际触发时间——你可以亲眼检查它是否如你所愿。
5 个字段详解
* * * * *
│ │ │ │ │
│ │ │ │ └── 星期(0-6 或 SUN-SAT;某些方言用 1-7)
│ │ │ └────── 月份(1-12 或 JAN-DEC)
│ │ └────────── 月份中的某天(1-31)
│ └────────────── 小时(0-23)
└────────────────── 分钟(0-59)
每个字段可以是:
- 具体数字:
5(意思是"恰好这个值") - 列表:
1,15,30(意思是"这些值中的任何一个") - 范围:
1-5(意思是"从此到彼") - 步进:
*/15(意思是"从 0 起,每 N 个值")——所以分钟字段里的*/15表示"0、15、30、45" - 通配符:
*(意思是"任意值")
记住语法之后常见的几种写法:
* * * * *—— 每分钟(著名的"我忘了写 schedule"表达式,会在凌晨 3 点把你叫醒)*/5 * * * *—— 每 5 分钟0 * * * *—— 每小时整点0 9 * * *—— 每天上午 9 点0 9 * * 1-5—— 工作日上午 9 点(教科书级的"工作时间"任务)0 0 1 * *—— 每月 1 号 00:000 0 * * 0—— 周日 00:00(一周边界)15 14 1 * *—— 每月 1 号下午 2:150 */6 * * *—— 每 6 小时(0、6、12、18 点)
方法一:Ai2Done Cron 解析器(部署前目视确认)
Ai2Done Cron 解析器 会把任何表达式翻译成人话,并展示未来 10 次的实际触发时间。流程:
- 在任何浏览器中打开 /tools/cron_parser。
- 粘贴你的表达式——例如
0 9 * * 1-5。 - 立刻看到:
- 人话翻译:"周一到周五 09:00 AM"
- 按本地时区列出的未来 10 次触发时间
- 按字段拆解,告诉你每段匹配了哪些值
- 不合法表达式的校验错误(例如
0 9 32 * *——根本没有"32 号")
- 切换方言:在经典 cron、Quartz、AWS EventBridge、Kubernetes 间切换,匹配你的调度器。
工具完全在客户端运行,底层用 cronstrue 做自然语言翻译、cron-parser 算下次触发。你的表达式绝不会传到服务器。
实战小贴士:任何由 cron 驱动的生产任务,部署前先把表达式粘到解析器里,亲眼确认未来至少 3 次触发时间符合预期。这能在 5 秒内拦下"我以为是每 6 小时一次,但实际写成了 0 6 * * *,结果每天 6 点只跑一次"这类经典错误。
方法二:crontab.guru 网站
如果你已经在浏览器里了,crontab.guru 是 cron 解释的非官方业界标准。它是一个单页网页工具,核心能力相同——粘表达式、看英文翻译。与 Ai2Done 解析器的差别:
- 服务端运行(你的表达式会出现在他们的访问日志里)
- 没有按字段拆解的视图
- 只支持经典 cron(无 Quartz、无 AWS EventBridge 方言)
- 免费且优秀近 10 年
对非敏感表达式来说它是不错的选择。对可能泄漏信息的表达式(比如某些 Quartz 方言中带自定义字段名的写法),本地解析器更安全。
方法三:在 dry-run 调度器里试运行
对高风险的 cron 任务(数据管道、计费跑批、面向客户的定时操作),最有把握的做法是先部署到 dry-run 环境:
- Kubernetes:以
suspend: true部署 CronJob,再通过kubectl describe检查算出来的下次触发时间。 - AWS EventBridge:创建规则但不挂任何 target,看其
NextInvocations。 - Airflow / Dagster:调度器 UI 通常会显示 DAG 未来 5-20 次的触发时间。
它能捕获解析器看不到的边角情况(你集群的 UTC 偏移、夏令时切换、调度器特有的小怪癖,例如 AWS EventBridge 的 cron(0 9 ? * MON-FRI *) 需要 6 字段+ ?)。
经典坑
Day-of-month 与 day-of-week 是 OR,不是 AND。0 0 1 * 1 在每月 1 号 00:00 触发,同时每个周一也触发——不是"1 号且必须是周一"。要 AND,用 Quartz cron 的 ? 表示"不指定具体值"——0 0 1 * ? 只在每月 1 号触发,不管星期几。
***/N 不是"每 N 单位",而是"从 0 起每 N 单位"。**所以 */30 * * * * 在每小时的 :00 与 :30 触发,不是"距上次运行 30 分钟"。如果你要真正的固定间隔调度,请用任务队列(Celery、BullMQ、Sidekiq)——cron 本质上是基于日历的,不是基于间隔的。
**时区默认值不可靠。**Linux cron 跑在系统时区;Docker 容器通常默认 UTC;AWS EventBridge 默认 UTC;Kubernetes CronJob 默认 API server 的时区(通常是 UTC)。如果你的任务需要"本地时间上午 9 点",显式配置时区——不要相信默认。
**夏令时会造成幽灵触发。**春季时钟跳过凌晨 2 点时,原本定在 2:30 AM 的任务那天不会运行;秋季回拨时则会运行两次。多数调度器有应对选项(Quartz 的 misfire 策略、Kubernetes 的 concurrencyPolicy),认真读你那一家的文档。
0 0 31 2 *——这是 2 月 31 日,它不存在。多数调度器会默默跳过。部署前先测一下。
我们是怎么做这个解析器的(技术细节)
Ai2Done Cron 解析器 构建于:
- cronstrue 做英语翻译(业界最好、支持所有主流方言、约 30 KB gzip)
- cron-parser 算未来触发时间(正确处理 DST、闰日、范围、步进)
- 一小段方言适配层:把 AWS EventBridge 的
cron(0 9 ? * MON-FRI *)(6 字段、年份可选)翻译成底层解析器期待的格式 - Web Crypto / SubtleCrypto 未使用——这里没有安全敏感内容,解析器只是便利工具
一个有意思的设计选择:我们刻意不提供 "Google Calendar 式选择器"。那种 UI 对新手友好,但容易让人记住选择器、而非底层语法。Cron 虽然密集,但 20 分钟可学会;我们更愿意帮你读懂它,而不是把它藏起来。
常见问题
Q:为什么有些调度器是 5 字段,有些是 6 或 7?
A:经典 Unix cron 是 5 字段(分钟、小时、日、月、周)。Quartz 在前面加秒、在后面加年(* * * * * * *)。AWS EventBridge 是 6 字段,且要求 day-of-month 与 day-of-week 必有一个为 ?。挑你调度器对应的方言。
Q:cron 中的 ? 是什么意思?
A:Quartz / AWS EventBridge 的扩展,表示"不指定具体值"。用在 day-of-month 与 day-of-week 之间消歧——只想其中之一匹配时用。经典 Unix cron 不支持。
Q:cron 中的 L 是什么意思?
A:Quartz 扩展,意为 "last"。L 在 day-of-month 表示"该月最后一天"(28/29/30/31 视情况);5L 在 day-of-week 表示"该月最后一个周五"。适合做月末任务而不必硬编码 28/29/30/31。
Q:cron 中的 W 是什么意思?
A:Quartz 扩展,意为 "weekday"。15W 在 day-of-month 表示"距 15 号最近的工作日"——用于"每月发薪日,但不要在周末"这类场景。
Q:怎么写"工作时间内每 5 分钟跑一次"?
A:*/5 9-17 * * 1-5 —— 每 5 分钟、9-17 点、工作日。在解析器里验证一下,未来 10 次触发时间应当符合预期。
Q:我的任务在夏令时切换时跑了两次,怎么修?
A:这是调度器特定的问题。Kubernetes CronJob 的 concurrencyPolicy: Forbid 能阻止并发;Quartz 有 misfire 策略;AWS EventBridge 通过始终运行在 UTC 来回避(也就是说,DST 是你应用层面的事)。
Q:能在 cron 里表达"每月第一个周一"吗?
A:经典 Unix cron 不行——需要应用层逻辑配合。Quartz cron 可以:0 0 0 ? * MON#1(每月第一个周一 00:00 触发)。
现在就试
在它跑进生产之前,先确认任何 cron 表达式:
粘贴、看清、再部署。无上传、无注册,你的表达式留在浏览器里。
相关阅读
- 永不上传你 Token 的隐私安全 JWT 调试器——同样的架构,应用于 JWT
- JSON、YAML、XML、CSV——一套工具的来回转换——你的 cron 任务很可能要读这些配置
- WASM 端处理:为什么我们让一切在你的浏览器内完成
- 浏览全部开发者工具
最后更新于 2026-06-14。Cron 解析器 100% 在你的浏览器内运行——你的表达式永远不会离开设备。我们没有任何关于你测试内容的服务器日志。