登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  php教程

PHP CLI 能用扩展但 PHP-FPM 不能用时怎么对比环境

来源:17golang原创

时间:2026-11-11 06:59:16 354浏览 收藏

我遇到过一类很容易误判的 PHP 问题:命令行里能执行某个扩展的函数,网站请求经过 PHP-FPM 却提示函数不存在。第一反应通常是重装扩展,结果 CLI 和 FPM 继续各说各话。真正要对比的不是“机器上有没有这个 so 文件”,而是两个 SAPI 最终加载了什么。

官方地址:https://www.php.net/manual/en/configuration.file.php

PHP CLI 与 PHP-FPM 可以使用不同的二进制、主 php.ini、附加扫描目录和扩展集合。先把这四组证据分别记下来,再只修改 FPM 对应配置;配置改完要重启或重新加载 FPM,不能拿 CLI 的结果代替 FPM 复查。
要点速览
  • php --ini 只能说明 CLI 的配置入口,不能证明 FPM 使用同一份文件。
  • 扩展差异要连同 extension_dir、附加 ini 文件和 SAPI 身份一起比较。
  • 修复时保存 FPM 配置副本,重启后再检查加载结果,回滚也只回 FPM 变更。

先固定四组对比字段

这次排查我会把问题拆成四张小表:运行二进制、主配置文件、附加扫描目录、已加载扩展。它们分别回答“谁在运行”“读了哪份 php.ini”“还读了哪些 .ini”“最终有哪些模块”。只看最后一项,最容易把路径问题误判成扩展安装问题。

PHP CLI 与 PHP-FPM 四组环境证据对比结构说明图
图1:结构说明图,把 CLI 与 PHP-FPM 的对比收敛为二进制、主 php.ini、扫描目录和已加载扩展四组证据;这不是运行截图。

先看 CLI,再拿到 FPM 的同名字段

CLI 的入口比较直接,先记录可执行文件、SAPI、主配置和扫描目录。下面的命令只输出诊断信息,注释说明每一组字段的用途。

# 记录 CLI 使用的二进制、主 php.ini 和附加扫描目录
command -v php
php --ini

# 记录 CLI 的 SAPI、主配置路径、扫描文件和已加载扩展
php -r '
// 把四组对比字段放在同一份输出里,便于和 FPM 结果逐项比较
echo "SAPI=" . PHP_SAPI . PHP_EOL;
echo "ini=" . (php_ini_loaded_file() ?: "none") . PHP_EOL;
echo "scanned=" . (php_ini_scanned_files() ?: "none") . PHP_EOL;
echo "extensions=" . implode(",", get_loaded_extensions()) . PHP_EOL;
'

# 使用实际的 FPM 二进制读取 FPM 侧信息;名称按发行版替换
command -v php-fpm || command -v php-fpm8.3
php-fpm -i | grep -E 'Server API|Loaded Configuration File|Scan this dir for additional .ini files|Additional .ini files parsed|extension_dir|^\w+ support' 

如果系统里的 FPM 程序名是 php-fpm8.2 或带完整版本号,就把最后一行换成实际路径。这里最重要的不是命令长短,而是 CLI 和 FPM 使用同一套字段:Server API 对应 SAPI,Loaded Configuration File 对应主配置,扫描目录和 extension_dir 则解释附加模块从哪里来。

差异出现在哪里,就在哪里处理

我通常按下面的顺序读结果。若二进制路径不同,先不要把一个版本的扩展复制给另一个版本;若主 php.ini 不同,优先确认 FPM 服务启动参数或发行版配置;若扫描目录不同,检查 FPM 是否读到了启用扩展的独立 ini;只有四项路径一致而扩展仍缺失时,才继续看扩展文件本身和加载错误。

差异通常说明处理方向
二进制不同CLI 与 FPM 可能来自不同 PHP 安装确认 FPM 服务使用的版本和模块目录
主 php.ini 不同同名配置项没有作用在两个 SAPI 上修改 FPM 对应的主配置
扫描目录不同启用扩展的独立 .ini 只被 CLI 读到补齐 FPM 的扫描目录或独立 ini
扩展集合不同加载顺序、文件名或扩展目录仍有差异检查 FPM 启动日志与扩展路径

PHP 官方文档说明,主配置文件之后还可能扫描 PHP_INI_SCAN_DIR 或编译时指定的目录,并按文件名顺序读取 .ini 文件。因此,CLI 的 php --ini 显示“已解析某文件”,并不能替代 FPM 侧的同名检查。

修复、重启和回滚都只围绕 FPM

确认差异后,我会先复制 FPM 要修改的配置,再改最小范围:补正确的 extension=... 行、修正扫描目录,或把服务指向正确的 PHP-FPM 二进制。不要把 CLI 的完整 php.ini 覆盖过去,因为它可能携带不同的路径、权限和开发环境设置。

# 先保存 FPM 配置副本,文件名带时间便于回滚
sudo cp /etc/php/8.3/fpm/php.ini /etc/php/8.3/fpm/php.ini.before-extension-change

# 修改 FPM 对应的独立 ini;路径按发行版实际目录替换
sudo editor /etc/php/8.3/fpm/conf.d/20-example.ini

# 让 FPM master 重新读取配置,再检查服务状态
sudo systemctl restart php8.3-fpm
sudo systemctl is-active php8.3-fpm

# 回滚时只恢复 FPM 文件,然后再次重启并复查
sudo cp /etc/php/8.3/fpm/php.ini.before-extension-change /etc/php/8.3/fpm/php.ini
sudo systemctl restart php8.3-fpm

图中的 master 与 children 是一个很实用的边界:配置修复后,已经存在的 FPM 进程不一定自动获得新模块,重启或按现场规范 reload 后才有复查意义。生产环境应按服务管理策略选择动作,并把变更前后的四组输出保存到工单或发布记录。

PHP-FPM 配置修复重启与回滚边界结构说明图
图2:边界结构图,展示 FPM 配置、扩展目录、主进程与子进程之间的修复和回滚关系;这不是运行截图。

值班复查清单

  • CLI 和 FPM 的二进制路径是否属于同一安装或同一版本。
  • 两边的主 php.ini、扫描目录和 extension_dir 是否分别记录。
  • 目标扩展是否出现在 FPM 的已加载集合中,而不是只出现在 CLI 输出。
  • 修改后是否重启或重新加载了正确的 FPM 服务,旧 worker 是否已经退出。
  • 回滚副本、服务状态和复查输出是否留在同一条变更记录中。

如果四组字段已经一致而扩展仍然缺失,再看 FPM 的启动日志和模块加载错误;如果只有 CLI 正常,优先回到 SAPI、配置文件和扫描目录这三层,不要先改业务代码。

相关问题

为什么 php -m 有扩展,网页仍提示不存在?

php -m 读取的是 CLI 进程的模块集合。网页通常经过 PHP-FPM,必须在 FPM 的运行环境中重新确认。

改了 php.ini 为什么马上不生效?

FPM 由 master 管理 worker,修改配置后需要按服务管理方式重启或重新加载,再检查新 worker 的配置和扩展集合。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>