跳到主要内容

读懂 cron 表达式:分时日月周五个字段一次讲清

从五个字段、四个特殊字符到每天每周每月的常见写法,把 cron 表达式拆开讲明白,顺带说清最容易翻车的日和周混淆,看完就能反向读懂任何一行 crontab。

发布于 作者 李雷
#cron #crontab #linux #定时任务 #运维

读懂 cron 表达式:分时日月周五个字段一次讲清

接手别人留下的服务器,在 /etc/crontab 里看到一行 0 9 * * 1,没有任何注释,心里没底删也不敢删。这是很多人跟 cron 打交道的真实场景。其实 cron 的语法并不复杂,五个字段加四个特殊字符,搞清楚结构以后,再陌生的一行也能读出来。这篇就把它拆开,从字段顺序讲到最坑人的那个细节。

五个字段:分、时、日、月、周

经典的 POSIX cron 一行有五个字段,按空格分开,从左到右依次是:

  1. 分钟:0 到 59
  2. 小时:0 到 23,用 24 小时制
  3. :1 到 31,指一个月里的第几天
  4. :1 到 12
  5. :0 到 6,0 和 7 都表示周日

记住顺序是关键,我习惯念成「分时日月周」,五个字念顺了就不会把日和小时写反。比如 30 8 1 1 * 读出来就是:1 月 1 日 8 点 30 分。最后一个字段写成 *,表示「周几都行」,所以这一行只看日期不看星期。

顺便说一句,有些系统会多带一两个字段。开头多一个秒字段就是 6 字段(BusyBox 和部分应用调度器用),末尾多一个年字段就是 7 字段(Quartz / Spring 这套)。判断办法很简单,数空格分出来几个词就是几字段,不用记一堆 flavour 开关。

四个特殊字符:星号、斜杠、逗号、连字符

每个字段里都能用这四个符号,组合出各种节奏:

  • * 星号:任意值。放在分钟位就是每分钟,放在月份位就是每个月。
  • */N 斜杠:每隔 N 个单位。*/15 放在分钟位是每 15 分钟。
  • , 逗号:列举多个具体值。0,30 放在分钟位是每小时的 0 分和 30 分。
  • - 连字符:一段连续范围。9-17 放在小时位是 9 点到 17 点这一段。

四个符号还能套着用。0-30/5 表示在 0 到 30 这段里每 5 分钟一次,也就是 0、5、10、15、20、25、30 这几个点。范围、步长、列表在五个字段里都能用,熟练以后就像搭积木。

三种最常用的写法

把字段和符号配起来,日常九成的需求就这几种:

  • 每天某点:0 9 * * *,每天上午 9 点整。日、月、周全是 *,所以天天跑。
  • 每周某天:0 9 * * 1,每周一上午 9 点。最后一位是 1,锁定星期一。
  • 每月某号:0 9 1 * *,每月 1 号上午 9 点。第三位是 1,锁定每月第一天。

我自己第一次配监控告警时,想要「每 7 分钟跑一次」,顺手写了 */7 * * * *,以为很均匀。后来用解释器看了下命中网格才发现,它在 :00、:07、:14 一路到 :56,然后跳回下一个整点的 :00,中间只隔了 4 分钟。因为 60 除不开 7,每到整点就会漂一下。后来改成 0,15,30,45 * * * *,这才是告警管线真正要的干净节奏。这个教训让我养成习惯:任何 */N 写法,信任它均匀之前先眼见为实。

一个真实例子:0 9 * * 1

拿开头那行举例。0 9 * * 1 拆开看:分钟 0、小时 9、日 *、月 *、周 1。读出来就是「每周一上午 9 点整触发」。如果把它粘进 Cron 表达式解释器,除了这句中英文解释,还能直接看到下 20 次具体触发时间,每行带星期标注,以及一张 24 时 × 60 分的命中热力图。一眼就能确认它是周一的周会提醒,而不是每天都跑的任务。

最容易搞错的:日和周

这是 cron 最大的坑,没有之一。日(第三位)和周(第五位)是两个独立的过滤条件,很多人会把它们混淆。

  • 0 0 * * 1每周一的 0 点,跟几号无关。
  • 0 0 1 * *每月 1 号的 0 点,跟星期几无关。

更微妙的是:当日和周同时都不是 * 的时候,多数 cron 实现是「或」的关系,而不是「与」。也就是说 0 0 13 * 5 会在「每月 13 号」或者「每个周五」都触发,而不是只在「13 号正好是周五」时触发。这个行为跟直觉相反,踩过一次就再也忘不了。拿不准的时候,把两种写法都粘进解释器对比一下运行列表,比在生产环境上等结果靠谱得多。

还有几个常见的「永远跑不起来」的坑:0 0 31 2 * 要求 2 月 31 日,而 2 月根本没有 31 号,真实 cron 会一整年静默不跑;0 0 30 2 * 只有闰年才触发。这类问题肉眼很难发现,交给工具两秒就能查出来。

收尾

cron 的结构其实很规整:五个字段定位「分时日月周」,四个特殊字符控制节奏,剩下的全是组合。真正需要小心的就是日和周这对容易混的字段,以及 */N 不一定整除的细节。写完一行别急着上线,反向读一遍、看一眼下几次触发时间,基本就能避开大多数事故。如果还要把触发时间换算到别的时区,可以接着用 时区转换器 把第一次触发时间换过去。


Made by Toolora · Updated 2026-06-13