Crontab Guru

粘贴一个 cron 表达式,即可获得逐字段的通俗英文解释,明白它到底在做什么。无需记住字段顺序,也不用去查取值范围:Guru 会逐一讲解五个字段(分钟、小时、日(月内)、月份和星期),并从左到右解读整个表达式。适合在部署前检查 crontab 中的某一行,或解释一段接手过来的配置。

如何使用 Guru

  1. 1

    粘贴表达式

    把任意标准的 5 字段 cron 表达式(例如 `0 9 * * 1-5`)复制到输入框中。

  2. 2

    请求解释

    点击 Explain Cron,工具会逐行返回每个字段的说明:分钟、小时、日(月内)、月份和星期。

  3. 3

    阅读说明

    说明以英文生成,例如 "Minute: every 5 minutes" 或 "Hour: from 9 through 17."

  4. 4

    部署前先核对

    在把它写进 crontab、CI 配置或 Kubernetes 清单之前,先用这段说明确认调度行为符合你的预期。

字段速查表

 ┌───────────── 分钟 (0-59)
 │ ┌─────────── 小时 (0-23)
 │ │ ┌───────── 日(一个月中的第几天,1-31)
 │ │ │ ┌─────── 月 (1-12 或 JAN-DEC)
 │ │ │ │ ┌───── 星期几 (0-6 或 SUN-SAT;周日 = 0 或 7)
 │ │ │ │ │
 * * * * *

cron 表达式中的运算符

运算符 含义 示例
* 所有值 * * * * *
, 值列表 0,15,30,45
- 范围 9-17
/ 步长(起始值/步长) */50-30/5
L 最后(当月最后一天,或最后一个匹配的星期几,Quartz) L5L
W 最近的工作日 15W(Quartz)
# 当月第 N 个匹配的星期几 1#3(Quartz)
? 不指定具体值 仅 Quartz 支持

阅读顺序很重要

0 */2 * * 1-5 从左到右读作:第 0 分钟、每 2 小时、任意日、任意月、周一到周五。人们有时会出于习惯从右往左读这些字段而被搞糊涂;一定要从“分钟“开始读。

“每 X 分钟”的陷阱

*/10 * * * * 会在第 0、10、20、30、40、50 分钟执行,而不是“从任务创建那一刻起每 10 分钟一次“。cron 的步长始终从该字段取值范围的起点开始计算。如果你在 12:03 部署任务,首次运行会在 12:10,而不是 12:13。

对于确实需要“距上次运行 N 分钟后“执行的任务,请使用带持久计时器的调度器(使用 OnUnitActiveSec 的 systemd 定时器,或在应用层调度并保存上次运行的时间戳)。

值得了解的 cron 陷阱

  • 同时设置了“日“和“星期几“:大多数 cron 实现会按“或“逻辑处理,多半不是你想要的结果。
  • 步长为 0*/0 无效。
  • 范围跨过午夜:表示小时的 22-2 在传统 cron 中不起作用;请使用 22-23,0-2
  • 2 月 30 日:像 0 0 30 2 * 这样的计划永远不会执行。
  • 夏令时(DST)的歧义:安排在凌晨 2 点到 3 点之间的任务,在夏令时切换日可能会执行两次,也可能一次都不执行。

cron 与现代调度器的对比

Unix 的 cron 至今仍随处可见,但对于关键任务,你大概会需要下面这些:

  • systemd 定时器:能补上漏掉的运行、支持随机偏移、从 unit 文件读取配置。
  • Kubernetes CronJob:声明式,支持重试,并在 1.25 及以上版本支持时区。
  • Airflow / Prefect / Dagster:适用于存在依赖关系、重试、回填和可观测性需求的任务。
  • GitHub Actions 定时计划:5 字段 cron,仅支持 UTC,最小间隔 5 分钟,尽力而为(best-effort)地交付。

cron 本身是一种很好的格式,但对于绝不能错过的任务来说,它是个糟糕的调度器。

常见问题

因为在标准 cron 中,星期几的 0 表示周日(7 也表示周日,因此两种约定都支持),周一是 1。而 Quartz 把星期几编号为 1 到 7,并把周日记作 1,这常常让在不同实现之间切换的人栽跟头。

传统的 Unix cron 运行在服务器的本地时区,也就是 /etc/timezone 所指定的时区。Kubernetes 的 CronJob、GitHub Actions 以及大多数云端调度器默认都使用 UTC。请务必确认,并尽量使用 UTC,以避免夏令时带来的意外。

传统 cron 无法直接表达这一点。变通做法是:每周一都运行,并在脚本里检查日期:[ $(date +%d) -le 7 ] && ./job.sh。Quartz 则用 1#1 原生支持。

不能。每个计划都需要单独占一行。不过你可以用列表把多个时间点合并到一行:0 9,17 * * * 会在上午 9 点和下午 5 点运行。对于无法用一行表达的计划,请添加多行,指向同一条命令。

相关工具