>_
🛠 工具与效率 · 3 分钟阅读 教程

Cron 表达式速查:常用写法、时区陷阱和平台差异

5 个字段分别是什么意思、常用写法速查表、“日”和“周”同时设置的特殊规则,以及 Linux、Kubernetes、GitHub Actions、Spring 之间的差异。

Cron 表达式几乎每个后端开发者都写过,但很少有人能一次写对所有细节。这篇是一份可以收藏的速查表,最后附上几个常见的坑。

5 个字段

标准 cron 表达式由 5 个字段组成,用空格分隔:

┌───────── 分钟 (0–59)
│ ┌─────── 小时 (0–23)
│ │ ┌───── 日 (1–31)
│ │ │ ┌─── 月 (1–12 或 JAN–DEC)
│ │ │ │ ┌─ 星期 (0–7,0 和 7 都是周日,或 SUN–SAT)
│ │ │ │ │
* * * * *

每个字段可以使用:

符号含义例子
*任意值* 在小时字段表示每小时
,列表1,15 表示 1 号和 15 号
-范围9-17 表示 9 点到 17 点
/步长*/15 表示每隔 15 个单位

常用写法

表达式含义
* * * * *每分钟
*/5 * * * *每 5 分钟
0 * * * *每小时整点
0 */2 * * *每 2 小时
0 0 * * *每天 0 点
30 8 * * *每天 8:30
0 9 * * 1-5工作日 9:00
0 9,18 * * 1-5工作日 9:00 和 18:00
*/10 9-18 * * 1-5工作日 9 点到 18 点之间,每 10 分钟
0 0 * * 0每周日 0 点
0 3 * * 6每周六 3:00
0 0 1 * *每月 1 号 0 点
0 0 1,15 * *每月 1 号和 15 号
0 0 1 */3 *每季度第一天
0 0 1 1 *每年 1 月 1 日
@daily等同于 0 0 * * *
@weekly等同于 0 0 * * 0
@monthly等同于 0 0 1 * *

写完不确定对不对?粘贴到 Cron 表达式解析 里,会给出中文说明和接下来 10 次的执行时间。

坑 1:“日”和“周”同时设置时是“或”

0 0 1 * 1

很多人以为这表示“每月 1 号,且是周一”。实际上,在标准 cron 中,日和周都不是 * 时,只要满足其中一个就会执行:每月 1 号会执行,每个周一也会执行。

坑 2:时区

cron 按运行它的那台机器(或平台)的时区执行:

  • 云服务器、容器的默认时区经常是 UTC,比北京时间晚 8 小时。写 0 9 * * * 想要北京时间早上 9 点,在 UTC 的机器上实际会在北京时间 17 点执行;
  • GitHub Actions 的 schedule 默认按 UTC 计算;
  • Kubernetes CronJob 支持通过 timeZone 字段指定时区,例如 Asia/Shanghai。

要换算时间,可以用 时间戳转换 对照 UTC 和本地时间。

坑 3:不同平台的“方言”

平台字段数说明
Linux crontab5标准写法
Kubernetes CronJob5标准写法,可用 timeZone 指定时区
GitHub Actions5默认 UTC;高峰期可能延迟,最短间隔为 5 分钟
Spring @Scheduled6第一个字段是秒
Quartz6–7带秒和可选的年;日、周之一需要写 ?;支持 L、W、#

L(最后一天)、W(最近的工作日)、#(第几个星期几)这些写法只在 Quartz 等部分实现中可用,标准 crontab 不支持。比如“每月最后一天”在标准 cron 里无法直接表达,常见做法是每天执行,在脚本里判断明天是不是 1 号。

坑 4:任务重叠和静默失败

  • 如果任务的执行时间可能超过调度间隔,上一次还没结束、下一次就开始了,需要加锁(例如用 flock)或在平台上配置并发策略;
  • cron 默认不会通知失败,记得把输出重定向到日志,并为重要任务配置告警。

小结

  • 5 个字段:分、时、日、月、周;
  • 日和周同时设置时是“或”的关系;
  • 先确认运行环境的时区;
  • 跨平台复制表达式时,注意秒字段和扩展语法的差异。

本文用到的工具