
理解 Cron 语法
cron 表达式是一个由五个(或六个)字段组成的字符串,用于定义计划任务的运行时间。每个字段代表一个时间单位,它们共同构成一个自动重复的精确调度。
标准的五字段格式:
┌───────────── 分钟 (0–59)
│ ┌───────────── 小时 (0–23)
│ │ ┌───────────── 日期 (1–31)
│ │ │ ┌───────────── 月份 (1–12)
│ │ │ │ ┌───────────── 星期 (0–7,其中 0 和 7 都表示星期日)
│ │ │ │ │
* * * * *
某些系统(如 AWS EventBridge、Quartz Scheduler)会在分钟前增加一个秒字段,从而形成六字段格式。
特殊字符说明
| 字符 | 含义 | 示例 |
|---|---|---|
* |
任意值 | * * * * * — 每分钟 |
, |
值列表 | 分钟字段 1,15,30 — 在第 1、15、30 分钟 |
- |
范围 | 小时字段 9-17 — 从上午 9 点到下午 5 点 |
/ |
步长 | 分钟字段 */5 — 每 5 分钟 |
L |
最后 | 日期字段 L — 月份的最后一天 |
# |
第 N 个工作日 | 2#3 — 当月第三个星期二 |
? |
不指定值 | 用于日期或星期字段,当另一个字段已设置时 |
最常见的 Cron 调度
以下是开发人员最常用的模式:
每分钟
* * * * *
生产环境中很少使用。对于任何有意义的 I/O 操作,请避免使用此模式——它每天运行 1440 次。
每 5 分钟
*/5 * * * *
健康检查、轮询任务和轻量级后台作业最常用的调度。
每 15 分钟
*/15 * * * *
适合同步数据或检查更新,而不会压垮服务。
每小时(整点)
0 * * * *
在每小时的第 0 分钟运行:1:00、2:00、3:00...
每小时(指定分钟)
30 * * * *
在每小时的第 30 分钟运行:1:30、2:30、3:30... 用于避开服务器繁忙的整点时刻。
每天午夜运行一次
0 0 * * *
每日清理任务、报告生成、缓存失效。
每天凌晨 2 点运行一次
0 2 * * *
数据库备份、日志轮转——安排在非高峰时段。
每天上午 8 点和下午 6 点运行
0 8,18 * * *
每日两次的摘要或邮件简报。
每个工作日早上 9 点运行
0 9 * * 1-5
仅在工作时间运行的任务:发送晨间报告、同步日历。
每周一午夜运行
0 0 * * 1
每周任务:生成周报、清理旧会话。
每月第一天运行
0 0 1 * *
月度计费周期、订阅续订、报告生成。
每月最后一天运行
0 0 L * *
注意:L 在 Quartz 和一些扩展 cron 解析器中受支持,但标准 Unix crontab 不支持。对于标准 cron,请使用检查日期的脚本。
完整参考表
| 调度 | 表达式 | 备注 |
|---|---|---|
| 每分钟 | * * * * * |
每天 1440 次 |
| 每 5 分钟 | */5 * * * * |
每天 288 次 |
| 每 10 分钟 | */10 * * * * |
每天 144 次 |
| 每 15 分钟 | */15 * * * * |
每天 96 次 |
| 每 30 分钟 | */30 * * * * |
每天 48 次 |
| 每小时 | 0 * * * * |
每天 24 次 |
| 每 2 小时 | 0 */2 * * * |
每天 12 次 |
| 每 6 小时 | 0 */6 * * * |
每天 4 次 |
| 每天午夜 | 0 0 * * * |
每天 1 次 |
| 每天中午 | 0 12 * * * |
每天 1 次 |
| 每个工作日 | 0 0 * * 1-5 |
每周 5 次 |
| 每个周末 | 0 0 * * 6,0 |
每周 2 次 |
| 每周(周一) | 0 0 * * 1 |
每周 1 次 |
| 每月(1 号) | 0 0 1 * * |
每月 1 次 |
| 每月(15 号) | 0 0 15 * * |
每月 1 次 |
| 每年(1 月 1 日) | 0 0 1 1 * |
每年 1 次 |
不同环境中的 Cron
基本语法相同,但每个平台都有其特点。
Linux / Unix crontab
# 编辑 crontab
crontab -e
# 查看当前 crontab
crontab -l
# 系统级 crontab 位于 /etc/cron.d/
# 每行格式:分钟 小时 日期 月份 星期 用户 命令
*/5 * * * * deploy /usr/bin/python3 /opt/scripts/check.py
GitHub Actions
on:
schedule:
- cron: '0 9 * * 1-5' # 工作日 UTC 时间上午 9 点
GitHub Actions 使用 UTC。最小间隔为每 5 分钟,高负载时作业可能延迟。
AWS EventBridge (CloudWatch Events)
AWS 使用六字段格式,秒在前,分钟其次:
cron(0 12 * * ? *) # 每天中午 UTC
cron(0/5 * * * ? *) # 每 5 分钟
注意:AWS 在日期或星期字段中使用 ? 代替 *,当另一个字段已指定时。
Node.js (node-cron)
const cron = require('node-cron');
// 每 5 分钟
cron.schedule('*/5 * * * *', () => {
console.log('每 5 分钟运行任务');
});
// 每个工作日早上 9 点
cron.schedule('0 9 * * 1-5', () => {
sendMorningReport();
});
Python (APScheduler)
from apscheduler.schedulers.blocking import BlockingScheduler
scheduler = BlockingScheduler()
@scheduler.scheduled_job('cron', hour=9, minute=0, day_of_week='mon-fri')
def send_daily_report():
print('发送报告...')
scheduler.start()
常见错误
未使用 UTC — 大多数 cron 系统以 UTC 运行。"午夜"的任务可能在您的当地时间中午触发。始终检查调度器使用的时区并明确记录。
在所有字段中使用 * — * * * * * 每分钟触发一次。如果任务执行时间超过 60 秒,重叠执行会堆积。请添加锁定或至少使用 */5。
日期和星期字段的交互 — 在标准 cron 中,如果两个字段都设置了(非 *),则任务在任一条件满足时运行,而不是两者同时满足。这是许多意外额外运行的根源。在支持 ? 的系统中使用 ? 明确表示"我不关心这个字段"。
无错误告警 — 失败的 cron 任务通常静默失败。始终将 stderr 重定向到日志文件,并设置监控或告警以捕获失败运行。
# 捕获 stdout 和 stderr
*/5 * * * * /opt/script.sh >> /var/log/script.log 2>&1
常见问题
如何让 cron 任务从午夜开始每 2 小时运行一次?
0 */2 * * * — 在 0:00、2:00、4:00、... 22:00 运行。
如何让 cron 任务在上午 9:30 和下午 3:30 运行?
30 9,15 * * *
cron 表达式能否在每月的最后一个工作日运行? 标准 cron 不支持。您需要一个计算该日期的脚本,或使用扩展调度器如 Quartz。
cron 支持的最小间隔是多少?
标准 cron 支持最小到每分钟(* * * * *)。对于亚分钟间隔,请使用进程管理器、消息队列或支持秒的调度器。
→ 使用 Crontab Generator 可视化构建和验证任何 cron 表达式——无需记忆语法。