hyperf定时任务不执行大概率是cron表达式错误:需严格使用5段格式(分、时、日、月、周),禁用年字段;秒级调度须显式启用毫秒模式;务必配置timezone避免时区漂移;注意空格和符号全角/半角问题;建议用在线工具校验并查日志确认加载情况。

Hyperf 定时任务不执行,很大概率是 Cron 表达式写错了——它看着简单,但格式、时区、字段顺序、特殊字符含义稍有偏差就会静默失效,连报错都没有。
确认 Cron 表达式格式是否合法
Hyperf 默认使用标准 5 段 cron(分、时、日、月、周),不支持年字段;若需秒级调度(6 段),必须显式开启 enable_millisecond => true,否则第六段会被忽略或直接报错不加载。
- ✅ 正确(每 5 分钟):
'*/5 * * * *' - ✅ 正确(每 3 秒):
'*/3 * * * * *'(需配置中启用毫秒模式) - ❌ 错误(含年字段):
'0 0 * * * 2026'—— Hyperf 不识别第 6 字段为年,会跳过该任务 - ❌ 错误(空格不一致或中文符号):
'*/5 * * * *'(全角空格)、'*/5 * * * *?'(中文问号)——解析失败,任务不注册
检查时区是否与表达式预期一致
Hyperf 默认用系统本地时区解析 cron,但你写的 '0 2 * * *' 是按「北京时间」设计的,如果服务器时区是 UTC,那实际就在凌晨 10 点执行。任务没在预期时间跑,八成是时区漂移。
- 务必在
config/autoload/crontab.php中显式指定:'timezone' => 'Asia/Shanghai' - 避免依赖
date_default_timezone_set(),Hyperf 的 crontab 调度器只认配置里的 timezone - 验证方式:启动服务后查日志,看 Crontab manager 打印的时区是否为你设置的值
排查表达式语义是否符合业务意图
常见逻辑误解会导致“看似正确,实则永不触发”:
-
'0 0 31 * *':想每月 31 号执行 → 实际只在有 31 日的月份(1、3、5…)运行,2 月、4 月等直接跳过 -
'0 0 * * 7':想周日执行 → 注意:Hyperf 默认周日是0或7,但部分版本只认0,建议统一用'0 0 * * 0' -
'0 0 1,31 * *':想每月 1 日和 31 日 → 若当月无 31 日(如 4 月),该规则整月失效,不会退化为只跑 1 日
快速验证与调试方法
别靠猜,用工具+日志交叉验证:
- 启动服务后,第一眼看控制台是否有类似
[INFO] Crontab manager started with 3 tasks—— 数量不对说明某些任务因语法错误被跳过 - 临时把 rule 改成
'* * * * *'(每分钟),加一行file_put_contents('/tmp/cron.log', date('c')."\n", FILE_APPEND);,确认是否真能触发 - 用在线 cron 表达式校验工具(如 crontab.guru)比对语义,再对照 Hyperf 文档确认其是否支持该写法
- 查看
var/log/hyperf.log,搜索crontab或scheduler,看是否有Invalid cron expression类警告(部分版本会静默丢弃)











