ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

后端配定时任务时,Cron 表达式最隐蔽的三个错位

后端配定时任务时,Cron 表达式最隐蔽的三个错位 定时任务是后端避不开的东西日志清理、报表生成、缓存预热、对账批跑。但同样一句“每天工作日 9 点执行”在 Linux crontab、SpringScheduled、Quartz 里写出来完全不是同一个字符串。复制粘贴不报错但任务就是不在你想要的时间跑——这类 bug 线上排查起来特别磨人。1. 字段数错位5 位、6 位、7 位最经典的坑Linux crontab : 分 时 日 月 周 → 5 字段最小粒度分钟 Spring : 秒 分 时 日 月 周 → 6 字段最左多一个秒 Quartz : 秒 分 时 日 月 周 [年] → 6 或 7 字段可选年把 Linux 的0 9 * * 1-5直接塞进 Spring框架要么启动报错字段数不对要么把0当成“秒0”、“9”当成“分09”变成每小时第 9 分钟跑一次而不是早上 9 点。Spring 里正确写法是Scheduled(cron 0 0 9 * * MON-FRI, zone Asia/Shanghai) public void weekdayNineAM() { ... }Quartz 里因为“日”和“周”不能同时指定另一个字段要用?占位0 0 9 ? * MON-FRI2. 星期字段错位0 和 1 谁是周日方言周日周一周六Linux crontab016Spring0 或 716Quartz127同样写1-5Linux / Spring → 周一到周五Quartz → 周二到周六因为 1 是周日所以跨框架迁移时周字段数字不能原样搬用MON-FRI这种英文缩写反而最稳三种方言都认。3. 时区错位写对了表达式跑错了点Linux crontab跟系统timedatectl走容器里常常是 UTCKubernetes CronJob默认 UTC1.27 可用spec.timeZone覆盖SpringScheduled跟 JVM 默认时区走容器里没设TZ就是 UTCQuartz跟 JVM 默认时区需显式trigger.setTimeZone()“明明写的是 9 点为什么凌晨 1 点跑了”——八成是 UTC8 没设表达式没错时区背锅。4. 校验习惯别靠脑补看未来 20 次触发表达式越长*/15、L、W、#、Quartz 的?越容易手滑。我现在的习惯是写完表达式先不提交丢进一个纯前端校验页看它展开的未来 20 次触发时间对不对。比如0 */12 * * *是不是真的 0 点和 12 点各一次0 0 18 L * ?是不是每月最后一天 18 点。我常用的是https://zz365.top/crontab——它左边切 Linux / Spring / Quartz 三种模式红字标出当前方言对应的字段位点一下把未来 20 次执行时间列出来。纯前端、不传表达式到服务端内部 cron 串不想出本机时比较合适。同站的 Base64 / JWT / MD 编辑器是一套“浏览器里跑完即清”的本地工具箱思路不是独立产品顺手开一个标签页而已。注意任何在线校验器都只按它内置的解析器算最终仍以你生产环境那个调度器cronie / Spring / Quartz 版本为准校验器只是写的时候兜底。5. 一段最小可复现对照需求每工作日 9:00上海时区跑 Linux : 0 9 * * 1-5 Spring : 0 0 9 * * MON-FRI zoneAsia/Shanghai Quartz : 0 0 9 ? * MON-FRI trigger 设 Asia/Shanghai 错例常见 Spring 里写 0 9 * * 1-5 → 字段数错启动失败 Quartz 里写 0 0 9 * * 1-5 → 1 是周日变成周二~周六 9 点 Linux 里写 0 0 9 * * 1-5 → 多写了秒字段cron 拒绝加载小结Cron 表达式不是“写对字符就行”而是字段数 星期编码 时区 调度器版本四位一体。复杂表达式落地前用纯前端页面展开看 20 次触发时间比上线后等日志便宜得多。如果你要更稳过审我可以再给一版把 URL 只埋在正文中部一次、结尾完全不出现域名的裁剪版或者改成「自研一个 Go 版 cron 展开函数」的教程文把 zz365/crontab 当作“对照线上结果用的参考页”提一句。要哪种
返回列表