端口被占用是hyperf启动失败最常见原因,需先执行php bin/hyperf.php stop优雅关闭,再用lsof或netstat查pid确认是否为残留hyperf或其他服务(如redis、node)占用,开发时可临时修改server.php端口验证。

端口被占用:failed to listen server port [0.0.0.0:9501], Error: Address already in use [98]
这是 Hyperf 启动失败最常遇到的报错,本质是目标端口已被其他进程监听。别急着 kill -9,先确认是不是残留的 Hyperf 进程没关干净。
- 执行
php bin/hyperf.php stop—— 这是官方推荐的第一步,能优雅关闭所有 worker 和 manager 进程 - 若命令无响应或报错,再查端口:
sudo lsof -i :9501或netstat -tulnp | grep :9501 - 重点看 PID 对应的 COMMAND:是
php进程(大概率是上一次没停掉的 Hyperf),还是redis-server、node、java等其他服务?Xdebug 监听(如listening on 9003)也常误占端口 - 开发时可临时改端口验证,修改
config/autoload/server.php中的port值,避免干扰他人调试
Swoole/Swow 扩展缺失或版本不匹配
报错像 Class "Swow\Socket" not found 或 PHP Fatal error: Uncaught Error: Class "Swoole\Http\Server" not found,说明框架配置的服务器引擎和实际环境不一致。
- 先确认扩展是否启用:
php -m | grep swoole或php -m | grep swow;再检查php --ri swoole输出的 version 是否在 Hyperf 官方文档支持范围内(例如 Hyperf 3.0 要求 Swoole ≥ 4.8.12,Swow ≥ 4.8.0) - 如果配置了
SwowServer::class但没装 Swow,要么按文档编译安装并写入php.ini的extension=swow.so,要么直接切回 Swoole:把config/autoload/server.php里的type改成Hyperf\Server\SwooleServer::class -
Socket is closed(0)这类错误,90% 是因为本地起了个“假 Redis”(比如用systemctl start redisd启动的非标准包),实际redis-server并没跑起来。用ps aux | grep redis和netstat -nalp | grep 6379双重确认
配置中心或 .env 加载失败导致启动卡住
现象是控制台没报错、没日志、进程挂起不动,或者报 Client error: GET 404 Not Found —— 很可能是 Nacos/ACM/Alibaba Config Center 配置项未就绪,框架在初始化阶段阻塞等待。
- 快速验证方法:临时在
.env中设CONFIG_CENTER_ENABLE=false,再启动。如果成功了,问题就锁定在配置中心连通性或 dataId 配置上 -
.env文件路径错误也会静默失败,尤其在协程中getcwd()可能变化。不要用Dotenv::createImmutable(__DIR__),改用绝对路径:Dotenv::createImmutable(__DIR__ . '/../') - 注解冲突如
Controller annotation cannot be repeated,常见于在类和方法上都写了#[Controller],或路由前缀嵌套定义两次,删掉冗余的即可
Crontab 组件升级引发 eventLoop 已创建错误
升级 hyperf/crontab 到 3.0.9 以上后,突然报 Swoole\Server::start(): eventLoop has already been created,这不是环境问题,而是组件初始化时机变了。
- 根本原因是新版本 crontab 在 BootManager 或 ProcessManager 中提前触发了 Swoole 事件循环初始化,而主 Server 启动时又试图再建一次
- 最稳方案:在
composer.json中锁死版本,例如"hyperf/crontab": "3.0.9",避免composer update自动升到不兼容版 - 若必须用新版,检查代码里是否在
BootManager、ProcessManager或自定义进程里手动调用了CrontabManager或CrontabCollector;有则移出,改用@OnWorkerStart回调中延迟加载 - 顺带一提:
php bin/hyperf.php server:watch是开发利器,但生产环境严禁开启,它会干扰真正的事件循环生命周期
真正难排查的从来不是单个报错,而是多个条件叠加:比如端口被占 + Crontab 初始化提前 + .env 路径错,三者同时存在时,错误日志可能只显示最表层那个。建议每次只改一个点,用 --debug 启动看完整堆栈,再结合 lsof、php --ri、ps aux 这几个命令交叉验证。











