Cron 表达式解析器

五个字段,以空格分隔;也可以使用 @daily 这类简写。

你接手了一份 crontab,里面满是 0 */2 * * 1-5、30 3 * JAN,JUL 1 这样的行。这个解析器会把每个字段展开成它实际匹配的取值,于是你不用再去猜 */2 到底覆盖了哪些时间,而是直接看到它选中的那 12 个小时,以及旁边标出的数量。除此之外,你还会拿到规范化后的 5 字段写法、表达式落进已知陷阱时的警告,以及按你所在时区算出的接下来 5 次运行时间。

如何解析 cron 表达式

  1. 1

    粘贴表达式

    一行 5 个字段(`* * * * *`):分钟、小时、日期、月份和星期。`@daily` 这类简写同样可以直接粘贴。

  2. 2

    看展开后的字段

    每个字段都会列出它匹配的取值以及这些取值的数量,因此小时字段里的 `*/2` 会显示 0、2、4,以及它覆盖的另外 9 个小时。

  3. 3

    核对下次运行预览

    接下来的 5 次运行时间,在你的浏览器里按你所在的时区算出。如果和你的本意对不上,就回头改表达式。

  4. 4

    读一读警告

    解析器会把陷阱标出来:日期和星期两个字段同时设了具体值、日历上根本不存在的日期,或者标准 cron 看不懂的运算符。

每个字段会展开成什么

一个字段不是一个值,而是一组值。搞清楚这组值有多大,往往就回答了你来这里想问的问题。

字段 范围 * 匹配 说明
分钟 0-59 60 个值 任务失控最常见的源头
小时 0-23 24 个值 24 小时制,绝不是 1-12
日期 1-31 31 个值 指每月第几天;小月会直接跳过不存在的那几天
月份 1-12 12 个值 也接受 JAN 到 DEC
星期 0-7 7 个值 0 和 7 都表示周日

字段内部可用的运算符:* 表示每一个值,1,5,10 是一个列表,1-5 是一个范围,*/15 是从范围起点开始计算的步长,0-45/15 则是在一个范围之内使用步长。

名称和简写都能识别

月份和星期的名称可以正常解析,并会展开成它们对应的数字,因此 30 3 * JAN,JUL 1 的月份会显示为 1、7,星期显示为 1。带名字的简写则会在其他处理开始之前,先被展开成 5 字段写法:

简写 展开为 含义
@yearly、@annually 0 0 1 1 * 1 月 1 日 0 点
@monthly 0 0 1 * * 每月 1 日 0 点
@weekly 0 0 * * 0 每周日 0 点
@daily、@midnight 0 0 * * * 每天 0 点
@hourly 0 * * * * 每小时整点

@reboot 同样能识别,但它没有可展开的时间计划:它只在机器启动时运行一次,因此没有运行时间可以预览。

值得一读的警告

  • 日期和星期同时设了具体值。 0 0 1 * MON 并不表示“每月 1 日,而且那天还得是周一”。当这两个字段都被限定时,标准 cron 按“或”来处理,因此这一行既会在每月 1 日执行,也会在每个周一执行。解析器会就此给出警告,下次运行预览同样遵循这条“或”规则。
  • 永远不会到来的日期。 0 0 30 2 * 要的是 2 月 30 日。这个表达式语法上挑不出毛病,cron 也会接受,但它永远不会执行。解析器会把这一点直接说出来,而不是甩给你一个没有任何解释的空列表。
  • Quartz 运算符。 L(最后一个)、W(最近的工作日)、#(第几个星期几)和 ? 属于 Quartz 的扩展,不是标准 crontab 的写法。它们出现在 5 字段的一行里时会被识别并标记出来,该字段显示的是 Quartz 运算符,而不是一串取值。运行时间不会被计算,因为标准 cron 根本不会执行这样一行。

哪些写法会被直接拒绝

  • 字段数量不对。 带秒的 6 字段 Quartz 写法,或者再带上年份的 7 字段写法,都会因为字段数量不符而被拒绝。
  • 超出范围的取值,例如分钟写成 75,或者月份写成 13。
  • 倒序的范围,例如 5-1。
  • 为 0 的步长,例如 */0。

每一条拒绝提示都会点明是哪个字段、哪个取值引起的,于是你只要改那一处,而不用把整行重写一遍。

时区

下次运行预览是在你的浏览器里计算的,用的是你设备上设置的时区。而 crontab 实际运行时跟的是承载它的那台机器的时区,所以如果那台服务器用的是 UTC 而你不是,比较之前请先把时间换算过来。

常见问题

不能当成时间计划来解析。带秒的 6 字段 Quartz 写法,或者再带上年份的 7 字段写法,都会因为字段数量不符而被拒绝。普通 5 字段一行里出现的 Quartz 运算符(L、W、#、?)是另一回事:它们会被识别并标记出来,但不会计算运行时间,因为标准 cron 同样不会执行这样一行。

常见原因有两个:你的设备和实际跑 crontab 的那台服务器之间存在时区差,或者日期和星期两个字段都设了具体值。当日期和星期同时被限定时,只要其中任意一个匹配,cron 就会执行,并不要求两者同时匹配,因此 0 0 1 * MON 的执行次数远比大多数人以为的要多。想快速看出某个字段是不是比你想的更宽,就看每个字段旁边标出的取值数量。

可以。Kubernetes 用的就是标准的 5 字段语法。唯一需要留意的是时钟:CronJob 跟的是集群的时区(除非 spec.timeZone 另有指定,否则就是 UTC),而这里的预览用的是你自己设备上的时区。

它们是 Linux cron 允许用来代替五个字段的带名字的简写。@daily(也写作 @midnight)等于 0 0 * * *,@weekly 等于 0 0 * * 0,@monthly 等于 0 0 1 * *,@yearly(也写作 @annually)等于 0 0 1 1 *,@hourly 等于 0 * * * *。其中任何一个粘贴进来,解析器都会告诉你它展开成的 5 字段写法。@reboot 是个例外:它在开机时运行,因此既没有时间计划,也没有运行时间。

相关工具

此工具还提供其他语言版本