如何读写 cron 表达式:五个字段与常用示例
每天凌晨 2 点备份、工作日上午 9 点发送报告、每十分钟检查一次状态——这里汇总了用 cron 设置定时任务所需的一切。
五个字段
标准 Unix cron 表达式由五个以空格分隔的字段组成:分钟(0–59)、小时(0–23)、日(1–31)、月(1–12)和星期(0–7,0 和 7 都表示星期日)。当所有字段都匹配时任务就会运行。
例如 0 2 * * * 表示第 0 分、2 点、每天、每月、星期不限——即每天凌晨 2:00。星号表示“任意值”。
┌───── 分钟 (0-59)
│ ┌─── 小时 (0-23)
│ │ ┌─ 日 (1-31)
│ │ │ ┌ 月 (1-12)
│ │ │ │ ┌ 星期 (0-7, 星期日=0 或 7)
│ │ │ │ │
0 2 * * *
四个特殊字符
组合这四个字符就能覆盖大多数调度需求。有些系统还接受 MON、JAN 这样的名称。
- *(任意):小时字段中的 * 表示每小时。
- ,(列表):1,15 表示每月 1 日和 15 日。
- -(范围):星期字段中的 1-5 表示周一到周五。
- /(步长):分钟字段中的 */10 表示 0、10、20……即每十分钟。也可以指定起点,如 5-59/15。
常用示例
写好表达式后,推算接下来几次的运行时间,确认它符合预期。注意步长是从 0 开始计算的,而不是从任务启动时开始:分钟字段中的 */45 会在每小时的 :00 和 :45 运行,而不是每隔 45 分钟。
*/5 * * * * 每 5 分钟
0 * * * * 每小时整点
30 9 * * 1-5 工作日 09:30
0 0 1 * * 每月 1 日零点
0 18 * * 5 每周五 18:00
0 3 * * 0 每周日 03:00
0 9,18 * * * 每天 09:00 和 18:00
0 0 1 1 * 1 月 1 日零点
常见陷阱
最著名的陷阱是同时设置“日”和“星期”。0 0 13 * 5 看起来像“13 号星期五”,但在标准 cron 中,当两个字段都不是 * 时,它们按 OR 组合:任务会在每月 13 日以及每个星期五运行。
第二个陷阱是“每月最后一天”。标准的五字段 cron 没有表示它的符号;常见的变通办法是在 28–31 日运行,并让脚本检查明天是否为 1 日。Quartz 等调度器支持 L,但它们使用含秒的六或七字段格式,与标准 cron 不兼容。
cron 使用哪个时区?
cron 遵循服务器的系统时区。大多数云服务器运行在 UTC,所以本想在北京时间上午 9 点发出的报告,可能在北京时间下午 5 点才发出。北京时间上午 9 点是 UTC 凌晨 1 点,因此在 UTC 服务器上应写成 0 1 * * *。
GitHub Actions 和 Kubernetes CronJob 默认也是 UTC。如果调度与实行夏令时的地区相关,要预期当地运行时间每年会有两次偏移一小时。
运维技巧
在 AIBIZAP cron 生成器中选择“每天”或“每周”即可自动生成表达式,无需记住语法也能把调度设置正确。
- 把繁重任务分散到 :07 或 :23 这样的分钟,而不是全部在 :00 启动。
- 如果一次运行可能在下一次开始前还没结束,加锁防止重叠。
- cron 的环境变量和 PATH 与交互式 shell 不同,脚本中请使用绝对路径。
- 记录每次运行的输出日志,确保失败不会被忽视。