核心答案:cron 表达式 = 分 时 日 月 周 五段,空格分隔。每天凌晨 3 点:0 3 * * *;每 5 分钟:*/5 * * * *;工作日 9:30:30 9 * * 1-5。记住段序口诀「分-时-日-月-周」,90% 的错误都是段序写反。
五段语法结构
```
┌ 分(0–59)
│ ┌ 时(0–23)
│ │ ┌ 日(1–31)
│ │ │ ┌ 月(1–12)
│ │ │ │ ┌ 周(0–6,0 和 7 都是周日)
* * * * *
```
四个特殊符号
| 符号 | 含义 | 示例 |
|---|---|---|
| * | 任意值 | * * * * * 每分钟 |
| */n | 每 n 步进 | */10 * * * * 每 10 分钟 |
| a-b | 区间 | 0 9-18 * * * 9 到 18 点整点 |
| a,b,c | 枚举 | 0 9,12,18 * * * 三个时刻 |
组合示例:*/15 9-18 * * 1-5 = 工作日 9–18 点每 15 分钟。
20 个常用表达式速查
| 需求 | 表达式 |
|---|---|
| 每分钟 | * * * * * |
| 每 5 分钟 | */5 * * * * |
| 每小时整点 | 0 * * * * |
| 每天零点 | 0 0 * * * |
| 每天凌晨 3 点 | 0 3 * * * |
| 每天 9:30 | 30 9 * * * |
| 每小时第 15/45 分 | 15,45 * * * * |
| 工作日 9 点 | 0 9 * * 1-5 |
| 周末 10 点 | 0 10 * * 6,0 |
| 每周一 8 点 | 0 8 * * 1 |
| 每月 1 号零点 | 0 0 1 * * |
| 每月最后一天零点(2 月特殊) | 0 0 28-31 * *(见踩坑) |
| 每季度首日 1 点 | 0 1 1 1,4,7,10 * |
| 每年 1 月 1 日 | 0 0 1 1 * |
| 工作日每 10 分钟(9–18 点) | */10 9-18 * * 1-5 |
| 每隔 2 小时 | 0 */2 * * * |
| 每天 6:00 和 18:00 | 0 6,18 * * * |
| 周日到周四 23 点 | 0 23 * * 0-4 |
| 每月 15 号中午 | 0 12 15 * * |
| 开机执行一次 | @reboot(非五段扩展) |
实例:三条真实需求
例一(数据库备份):每天凌晨 2:30 备份,避开业务高峰 → 30 2 * * * /scripts/backup.sh
例二(日志清理):每周日凌晨 4 点清理 7 天前日志 → 0 4 * * 0 find /logs -mtime +7 -delete
例三(接口巡检):工作时间每 10 分钟探测,非工作时间不打扰 → */10 8-19 * * 1-5 curl -s https://api/health
crontab 使用要点
crontab -e编辑、crontab -l查看、crontab -r清空(危险)- 命令用绝对路径:cron 的 PATH 极简(/usr/bin:/bin),脚本内 cd 到工作目录
- 输出重定向:
>> /var/log/job.log 2>&1,否则报错全丢 - 环境变量在 crontab 文件顶部显式声明
- 改完立即生效,无需重启服务
六个高频踩坑
- 段序写反:想写「3 点」写成
3 0 * * *(这是每月 3 号零点)——正确0 3 * * * - 百分号转义:命令中的 % 必须写成 \%,否则被当作换行
- 相对路径:脚本里 ./data 找不到——cron 工作目录不是脚本所在目录
- 「每月最后一天」:cron 不支持 L,用
0 0 28-31 * *配合脚本内判断 [ $(date -d tomorrow +\%d) -eq 1 ] - 「每 90 分钟」:*/90 不合法(分钟段 >59),拆成
0 0,3,6,9,12,15,18,21 * * *或写两行 - 时区:cron 按服务器系统时区执行,跨国服务器先 timedatectl 确认
常见误区
- 「日和周同时写是且的关系」:标准 cron 中「日」和「周」都非 * 时是或的关系(任一满足即触发),
0 9 1 * 1是每月 1 号和每周一都执行。 - 「改完 crontab 要重启」:不需要,保存即生效;不生效先查日志 grep CRON /var/log/syslog。
- 「秒级调度」:标准 cron 最小粒度是分钟,秒级任务用 systemd timer 或程序内循环。
- 「周末写 1-5」:1-5 是周一到周五(工作日),周末是 6,0 或 6,7。
用[cron 表达式计算器](/c/dev/cron)输入表达式立即看到未来 10 次执行时间,[时间戳转换器](/c/dev/timestamp)处理日志时间。