php与swoole.so的module api必须完全一致才能加载,否则报“unable to initialize module”错误;需用php -r "echo php_module_api;"和objdump核验双方abi,清理残留后指定正确php-config重装。

直接看错误信息里的两个 API 号:如果 php -v 显示的 PHP 编译 ABI(即 module API)和 swoole.so 的不一致,扩展就不可能加载成功——这不是配置问题,是二进制层面的硬冲突。
PHP 和 swoole.so 的 module API 不匹配
典型报错长这样:
PHP Warning: PHP Startup: swoole: Unable to initialize module<br>Module compiled with module API=220121212<br>PHP compiled with module API=20131226
这两个数字必须完全一样,差一位都不行。它不是版本号,是 PHP 内部 ABI 标识,由 PHP 主版本 + 编译参数共同决定。
常见诱因:
- 用 A 版本 PHP 的
phpize编译了扩展,却在 B 版本 PHP 下运行(比如 CLI 是 PHP 8.2,FPM 是 PHP 8.1) - 系统里装了多个
php-dev包(如 Ubuntu 上php8.1-dev和php8.2-dev共存),pecl install默认用了旧包 - Docker 构建时用了
php:8.2-cli镜像,但php-config被 PATH 优先指向了宿主机的 PHP 7.4
如何确认当前环境的真实 ABI
别信 which php 或面板显示,要逐个验证运行时实际调用的组件:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 查 CLI 环境:
php -v+php-config --version+php-config --extension-dir - 查 FPM 环境:进
www.conf找php_admin_value[extension_dir],再进该目录看swoole.so时间戳和所属用户 - 查扩展 ABI:用
php -r "echo PHP_MODULE_API;"(PHP 7.4+)或php --ri core | grep 'Module API' - 查 so 文件 ABI:
objdump -s -j .rodata swoole.so | grep -o '2[0-9]\{8\}'(输出第一个匹配数字就是它的 API)
重装前必须清理的残留项
ABI 错误往往是因为旧 so 文件还在被优先加载,新编译的压根没机会上场:
- 删掉所有
swoole.so:搜索find /usr -name 'swoole.so' 2>/dev/null和find ~/.phpenv -name 'swoole.so' 2>/dev/null - 清空
php.ini里所有extension=swoole行(包括注释掉的),尤其注意宝塔的www.conf里可能有php_admin_value[extension] - 删掉源码编译目录下的
autom4te.cache、config.status、Makefile,避免缓存污染 - 如果是
pecl install装的,先pecl uninstall swoole,再确认pecl list里已无记录
指定 php-config 重装才是唯一可靠路径
无论用 pecl 还是源码编译,只要没显式绑定 --with-php-config,就大概率出错:
- pecl 场景:
pecl install swoole-4.11.5(必须带版本号)后,立刻检查php -r "echo SWOOLE_VERSION;"输出是否匹配 - 源码编译场景:进入解压目录后,第一句必须是
/path/to/your/php/bin/phpize(比如/www/server/php/81/bin/phpize),再./configure --with-php-config=/www/server/php/81/bin/php-config - Alpine 用户放弃 pecl:改用
apk add php81-swoole(包名按实际 PHP 版本调整),musl libc 下自己编译纯属自找麻烦
最易被忽略的是:Docker 多阶段构建中,build 阶段的 php-config 和 final 阶段运行时的 PHP 完全可能是两个东西——哪怕镜像名一样,ABI 也可能因构建时间不同而分裂。










