五个字段是什么
标准 cron(Linux crontab)是五个字段,用空格分开:
分 时 日 月 周
* * * * *
| 字段 | 取值范围 | 说明 |
|---|---|---|
| 分 | 0-59 | |
| 时 | 0-23 | 24 小时制 |
| 日 | 1-31 | 几号 |
| 月 | 1-12 | 或 JAN-DEC |
| 周 | 0-7 | 0 和 7 都表示周日,或 SUN-SAT |
特殊字符
| 字符 | 含义 | 例子 |
|---|---|---|
* |
每一个取值都匹配 | * * * * * 每分钟 |
, |
列举 | 1,15 * * * * 每小时第 1 和第 15 分钟 |
- |
范围 | 0 9-18 * * * 9 点到 18 点整点 |
/ |
步长 | */5 * * * * 每 5 分钟 |
20 个常用表达式
| 表达式 | 含义 |
|---|---|
* * * * * |
每分钟 |
*/5 * * * * |
每 5 分钟 |
0 * * * * |
每小时整点 |
0 */2 * * * |
每 2 小时 |
30 3 * * * |
每天 3:30 |
0 0 * * * |
每天 0 点(见下文说明) |
0 9 * * * |
每天上午 9 点 |
0 9 * * 1 |
每周一 9 点 |
0 9 * * 1-5 |
工作日 9 点 |
0 0 1 * * |
每月 1 号 0 点 |
0 0 1 1 * |
每年 1 月 1 日 0 点 |
0 0 */2 * * |
每隔 2 天的 0 点 |
0 8,20 * * * |
每天 8 点和 20 点 |
0 0-5 * * * |
每天 0 点到 5 点的整点 |
*/10 9-18 * * 1-5 |
工作日 9-18 点每 10 分钟 |
15 14 1 * * |
每月 1 号 14:15 |
0 22 * * 1-5 |
工作日 22 点 |
23 0-23/2 * * * |
每天每隔 2 小时的 23 分 |
0 4 * * 0 |
每周日 4 点 |
0 0 1 */3 * |
每季度首月 1 号 |
几个容易踩的坑
坑一:0 0 * * * 是每天 0 点,不是「0 点 0 分之外不执行」
读法是「分=0,时=0,日=任意,月=任意,周=任意」,也就是每天 00:00。
很多人第一次看到 * 会以为「任意」是「随便什么时候」,其实它的意思是这一位不限制。
坑二:日期和星期不能同时指定
0 0 1 * 1 这种写法在不同实现里行为不同:
- Vixie cron(Linux 默认):两个条件是或的关系——每月 1 号或每周一都执行
- Quartz:会直接报错,必须把其中一个写成
?
也就是说 0 0 1 * 1 在 Linux 上一个月会执行四五次,不是一次。这是个很隐蔽的坑。
想表达「每月 1 号且是周一才执行」,标准 cron 做不到,得在脚本里自己判断。
坑三:时区不是你的时间
cron 用的是服务器时区。如果服务器是 UTC 而你在东八区,那 0 2 * * *(你以为的凌晨 2 点)实际是北京时间上午 10 点。
排查「任务怎么没在预期时间跑」时,先确认服务器时区:
bashtimedatectl # 或 date 看时区
坑四:环境变量不一样
cron 执行任务时的 PATH 和你在终端里不一样,很多命令会「找不到」。
解决办法:脚本里用绝对路径,或者在 crontab 开头显式声明环境变量:
bashPATH=/usr/local/bin:/usr/bin:/bin
坑五:前 5 分钟之外的秒级需求
标准 cron 最小粒度就是分钟,做不到「每 30 秒」。真有这个需求得用别的方式(比如脚本里循环 sleep,或者用 systemd timer)。
不同实现有差异
这是最容易出错的地方——同样是「cron 表达式」,不同框架的字段数不一样:
| 实现 | 字段数 | 说明 |
|---|---|---|
| Linux crontab | 5 | 分 时 日 月 周 |
Spring @Scheduled |
6 | 秒 分 时 日 月 周 |
| Quartz | 6 或 7 | 秒 分 时 日 月 周 [年] |
从 Linux 拷表达式到 Spring 是高频事故:Linux 的 0 0 * * * 直接贴进 @Scheduled,会被当成「秒=0,分=0,时=*」,变成每小时执行一次而不是每天一次。
迁移时务必确认目标框架的字段数,别直接复制。
另外 Quartz 里「不指定」要用 ? 而不是 *(因为日期和星期互斥),这也是它和标准 cron 的显著差异。
生成和验证
写复杂表达式(带步长、多值、范围混合)时手写容易错。可以用 Cron 表达式生成器 勾选时间,它会同时给出 Linux 5 段、Spring 6 段、Quartz 7 段三种写法,并用人话解释下次执行时间——正好能避开上面「字段数不同」这个坑。
生成完建议再核对一遍下次执行时间的提示,这是验证表达式最直接的方式——Cron 表达式生成器 会把这个时间用人话写出来。