生產環境常見多 PHP 版本共存,CLI 模式下不同用戶加載不同配置文件導致擴展加載失效。本文記錄一次 protobuf 擴展在 root 與普通用戶下表現不一致的完整排查過程。
php protoc-php.php ... 正常Unable to load dynamic library 'protobuf.so' - undefined symbol: zend_new_interned_stringsudo 後更多擴展報錯(curl、gd、json、redis 等均報 undefined symbol 或 cannot open shared object file)$ php -i | grep 'php.ini' # 普通用戶:/usr/local/php/lib/php.ini $ sudo php -i | grep 'php.ini' # root 用戶:/etc/php.ini
$ which php # /usr/local/bin/php $ sudo which php # /usr/bin/php
/usr/bin/php,/etc/php.ini 配置/usr/local/bin/php,/usr/local/php/lib/php.ini 配置PATH 優先 /usr/local/bin,使用新版本secure_path 或環境變量導致優先 /usr/bin,使用舊版本php.ini 嘗試加載新版本編譯的擴展(protobuf.so 等),API 版本不匹配(20090626 vs 20100525)導致符號缺失mv /usr/bin/php /usr/bin/php.bak cp /usr/local/bin/php /usr/bin/php驗證:
sudo php -v 顯示 5.4.6,擴展正常加載。
/etc/sudoers(visudo),確保 Defaults secure_path 包含 /usr/local/bin 且優先級高。
/usr/local/bin/php 絕對路徑,或設置別名 alias php=/usr/local/bin/php。
| 場景 | 建議 |
|---|---|
| 生產部署 | 使用版本管理工具(phpenv、phpbrew、Docker)統一版本 |
| 定時任務 | Crontab 中使用絕對路徑 /usr/local/php/bin/php |
| 多項目共存 | 每項目獨立 Docker 容器,避免版本衝突 |
| 排查命令 | 統一使用 php -i | grep 'php.ini' 和 php -v 驗證 |
| 擴展編譯 | 嚴格匹配目標 PHP 版本的 phpize、php-config |