Hyperf定时任务需注册CrontabDispatcherProcess进程并启用crontab.enable配置,否则完全静默失效;启动时应见“Crontab manager started”日志,且必须运行在CLI模式(非FPM)。

检查 CrontabDispatcherProcess 进程是否注册并启用
Hyperf 的定时任务不会自动运行,必须显式注册 CrontabDispatcherProcess 进程,否则所有 @Crontab 注解都会被忽略——连日志都不会输出,属于“完全静默失效”。
常见错误是只写了任务类、加了注解,但没在进程配置里声明调度器。启动时控制台也不会报错,只会安静跳过。
- 确认
config/autoload/processes.php中已包含该类(不是注释掉,也不是拼写错误):return [ Hyperf\Crontab\Process\CrontabDispatcherProcess::class, ]; - 如果使用了多环境配置(如
config/autoload/processes.php被覆盖),需检查实际生效的配置路径,运行php bin/hyperf.php config show processes验证输出是否含该类名 - 修改后必须重启服务(
php bin/hyperf.php start),热重载不生效 - Docker 环境下注意:若用
supervisord或自定义 entrypoint 启动,要确保bin/hyperf.php start是主进程,而非后台 fork 后丢失信号
验证 crontab.enable 配置是否为 true
即使进程注册了,crontab 组件仍可能被全局禁用。这个开关默认是 false,很多开发者复制模板时漏改。
检查 config/autoload/crontab.php 中的 enable 值:
- 错误写法:
'enable' => false或根本没定义该键 - 正确写法:
'enable' => true(必须是布尔值true,不能是字符串"true") - 验证命令:
php bin/hyperf.php config show crontab.enable,输出应为true - 若项目有环境变量覆盖(如
CRONTAB_ENABLE=1),需确认 env 解析逻辑是否将字符串转为了布尔值
启动日志里有没有 “Crontab manager started”
这是最直接的运行证据。没有这行日志,说明调度器压根没起来,90% 是前两步出了问题。
启动服务后,立刻查看控制台或日志文件(如 runtime/logs/hyperf.log):
- 正常应看到类似:
[INFO] Crontab manager started with 2 tasks - 若只有
[INFO] Server started却无 Crontab 相关日志,说明进程未加载或配置未生效 - 注意:Docker 容器中若日志被重定向或缓冲,需加
-u参数强制标准输出(php -d output_buffering=off bin/hyperf.php start) - 某些 IDE 或终端对 ANSI 颜色日志过滤严格,可临时关闭颜色:
php bin/hyperf.php start --no-ansi
为什么 crontab:run 命令不能替代进程调度
php bin/hyperf.php crontab:run 是个调试命令,它会手动触发一次所有匹配的任务,但它和生产调度无关——它不依赖 CrontabDispatcherProcess,也不走 cron 规则解析,更不会自动重复执行。
误把它当“启动定时任务”的方式,是典型认知偏差:
- 该命令每次运行只执行当前时刻匹配的任务,不维护状态、不轮询、不支持秒级精度
- 它绕过整个调度器流程,不经过
Parser、Scheduler、Executor,无法验证真实环境下的时间漂移、并发锁、时区等问题 - 在 Docker 或 supervisor 下,若只跑
crontab:run一次就退出,任务自然不会再执行 - 真正要测调度是否就绪,唯一可靠方式是:启动服务 + 等待至少一个完整周期(比如设
* * * * *,等 60 秒看日志)
最容易被忽略的是:Hyperf 的 Crontab 调度器依赖 swoole 的定时器机制,而该机制在非 CLI 模式(如 FPM)下不可用;如果你在 Nginx+PHP-FPM 环境下试图“启用 crontab”,它注定不会工作——这不是配置问题,是架构限制。


















