Swoole重复加载报错需检查多配置路径中的extension=swoole.so并清理重复项,PHP8.5协程需显式编译参数--enable-coroutine和正确php-config路径,推荐用OpenSwoole替代PECL默认swoole,禁用opcache.jit以防冲突,宝塔旧版so优先级高须手动指定新版路径或删除旧文件。

Swoole 扩展已加载但报错 “Module 'swoole' already loaded”
这是典型的重复加载冲突,不是没装上,而是 PHP 同时从多个位置加载了 swoole.so。宝塔面板、禾匠 loader、手动编译、PECL 安装四者混用时极易触发。
- 执行
php --ini查看所有被加载的配置文件路径,重点检查/etc/php.d/、/www/server/php/*/etc/php.d/和主php.ini里是否有多处extension=swoole.so - 宝塔自带的
swoole_loader_20_php72.so和原生swoole.so互斥——哪怕只启用了其中一个,另一个残留的extension=行也会让 PHP 尝试加载两次 - CLI 和 FPM 的配置完全独立:
php -m看的是 CLI 配置,而 Web 请求走的是 FPM;必须分别检查php.ini和www.conf中的php_admin_value[extension]设置 - 删除或注释掉所有重复项后,务必执行
bt 16(重载 PHP 配置)+systemctl restart php-fpm-xx,仅重启 Web 服务不够
PHP 8.5 下 Swoole 扩展加载成功但协程不可用
扩展能列出来、php --ri swoole 显示版本,不代表协程就真可用。PHP 8.5 对 ABI 更敏感,旧参数或错路径会导致协程函数静默失效。
- 关键编译参数必须显式带上:
--enable-coroutine(否则Swoole\Coroutine::sleep()直接报not available)、--with-php-config=/usr/bin/php-config8.5(路径带版本号,避免指向 PHP 8.1 的 config) - PECL 默认安装的是
swoole(v4.x),它不支持 PHP 8.5;应改用pecl install openswoole,OpenSwoole 26.2.0 是目前唯一明确声明全兼容 PHP 8.5 的发行版 - JIT 冲突是隐藏雷:
opcache.jit=call(PHP 8.5 默认)与 Swoole 协程 Hook 已知不兼容,高并发下 CPU 飙升或请求卡死,需在php.ini中设为opcache.jit=off或tracy
宝塔面板里 Swoole 版本混乱:明明装了 v4.x,php --ri swoole 却显示 v2.2
这不是版本没更新,而是宝塔软件商店按钮和你手动安装的扩展“打架”。商店安装的旧版会写死一个低版本的 swoole.so 到系统级扩展目录,优先级高于你编译的新版。
- 先查清实际加载的是哪个文件:
php --ri swoole | grep "extension",输出类似extension: /usr/lib64/php/modules/swoole.so,这个路径才是真正在跑的 - 宝塔默认把旧版放
/www/server/php/*/lib/php/extensions/no-debug-non-zts-20170718/这类目录,而你手动make install通常装到no-debug-non-zts-20230831/(对应 PHP 8.3+ ABI)——两个目录并存,PHP 加载了旧的那个 - 解决办法只有两个:删掉旧版 so 文件(
rm /usr/lib64/php/modules/swoole.so),或修改php.ini中的extension=指向你新编译的绝对路径,例如extension=/www/server/php/85/lib/php/extensions/no-debug-non-zts-20230831/swoole.so
真正麻烦的从来不是“怎么装”,而是“哪个版本、哪个 so、哪份 ini、哪种 PHP SAPI 在起作用”。四个维度一交叉,漏查一项就白忙半天。










