Ubuntu 服务器升级 PHP-FPM 后,旧代码常见的问题并不是单点故障,而是语法、扩展、默认配置和 Web 服务器转发方式同时变化,最后表现成 502、超时或业务逻辑异常。要把影响控制在可回滚范围内,比较稳妥的路径是先备份和审计,再尽量复用旧版运行习惯,必要时让新旧 PHP 版本并行运行,最后用测试和分阶段迁移把风险压下去。
升级前先做备份,给回滚留出口
在动 PHP-FPM 之前,先把站点代码、FPM 配置和关键日志备份出来。这样即使升级后配置跑偏,或者旧项目直接报错,也能快速恢复到原状态。
建议至少备份下面这些内容:
- 网站目录:
/var/www/html - PHP-FPM 配置:
/etc/php/7.x/fpm/pool.d/www.conf、/etc/php/7.x/fpm/php-fpm.conf - 相关日志:例如
/var/log/php7.x-fpm.log
原文中的备份命令如下,可以直接保留使用:
sudo cp -R /var/www/html /var/www/html_backup
sudo cp /etc/php/7.x/fpm/pool.d/www.conf /etc/php/7.x/fpm/pool.d/www.conf.backup
sudo cp /etc/php/7.x/fpm/php-fpm.conf /etc/php/7.x/fpm/php-fpm.conf.backup
这一步的价值不在“备份了什么”,而在于后面不管是调整配置、切换版本,还是做兼容性修复,都有明确的退路。
先审计旧代码,确认兼容性风险点
升级前最好先把代码库扫一遍,目标不是一次性改完,而是先知道哪些地方一定会出问题。可以借助 phpCompatibilityChecker 之类的工具做初步检查,再结合人工确认高风险位置。

重点看废弃函数和旧语法
旧项目里最常见的兼容性问题,通常集中在废弃 API 和过时语法上。例如:
mysql_*系列函数已经不适合继续保留,像mysql_connect()这类调用应改成mysqli_connect()或 PDO;- 短标签
<在新环境里容易引发解析问题,建议统一改成。
扩展、配置默认值和错误处理也要核对
除了语法,运行时环境的变化也很容易让旧代码“表面能跑、实际异常”。手动检查时,至少要关注这几类问题:
- 是否依赖旧版 PHP 扩展,例如
mcrypt在 PHP 7.2+ 已被移除; - 配置参数默认值是否变化,例如
request_terminate_timeout可能比旧版本更严格; - 错误处理行为是否一致,例如
@抑制错误在 PHP 8+ 中的表现和旧版本并不完全一样。
先把这些风险点列出来,后面做兼容修复时,优先级就会清楚很多。
把 PHP-FPM 配置调回旧项目可接受的行为
很多升级失败并不是代码完全不能跑,而是 PHP-FPM 的默认行为变了,旧项目原本依赖的运行方式被悄悄改掉。此时与其急着重写业务,不如先把关键配置项对齐。

进程管理方式不要随版本漂移
如果旧项目原来使用 pm = static,升级后最好保持一致。固定进程数的方式更接近旧环境,能够避免切到 dynamic 后因为频繁启停而引发性能波动。
超时和慢日志要延续原有策略
对于上传大文件、批处理或其他长耗时请求,request_terminate_timeout 是一个必须重新核对的参数。新版本默认值如果更短,就可能直接把请求掐断。
同时,慢日志配置也不要漏掉。像下面这些设置最好与旧环境保持一致:
slowlog路径,例如/var/log/php-fpm/slow.log- 慢请求阈值,例如
slowlog = 10s
这样做的意义很直接:升级后即便性能异常,也还能沿用原来的排查手段。
Unix socket 权限是 502 的高发点
如果站点通过 Unix socket 与 PHP-FPM 通信,例如 listen = /run/php/php7.x-fpm.sock,就要确认这些权限相关参数与旧版本一致:
listen.ownerlisten.grouplisten.mode,例如0666
这类参数一旦错位,最常见的表现就是 Web 服务器无法连接 FPM,最终直接报 502。
旧代码改不完时,用多版本共存过渡
如果项目体量大、依赖多,一次性改完并不现实。更稳的做法是在 Ubuntu 上同时运行新旧 PHP 版本,让旧业务继续走原来的版本,新业务或已完成适配的部分再切到新版本。

原文建议通过 ppa:ondrej/php 仓库安装多个 PHP 版本,例如 PHP 7.4 和 PHP 8.2,再由 Nginx 或 Apache 按域名或路径分流。
Nginx 按域名切换 PHP-FPM 版本
下面这段配置保留了原文思路:旧站点走 php7.4-fpm.sock,新站点走 php8.2-fpm.sock。
map $host $php_version {
default "8.2";
"old.example.com" "7.4";
}
server {
listen 80;
server_name old.example.com;
location ~ .php$ {
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
include snippets/fastcgi-php.conf;
}
}
server {
listen 80;
server_name new.example.com;
location ~ .php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
include snippets/fastcgi-php.conf;
}
}
这种做法适合把老域名、老业务完整挂到旧版本上,减少交叉影响。
Apache 用 SetHandler 指向不同 socket
如果你的环境是 Apache,可以通过 SetHandler 明确指定不同虚拟主机对应的 PHP-FPM socket:
ServerName old.example.com
SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://localhost"
ServerName new.example.com
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
重启 Nginx 或 Apache 后,不同域名就能分别指向不同 PHP 版本。这种过渡方式最大的好处,是不需要等所有旧代码一次改完再升级。
上线前要验证功能、日志和错误表现
升级完成后,不建议直接在生产环境试错。先在本地或测试环境把完整链路跑通,再决定是否切流量。
尽量搭接近生产的测试环境
可以使用 Docker 创建接近生产环境的容器,例如 ubuntu:22.04,然后安装对应版本的 PHP-FPM 和依赖,把旧代码放进去验证。这样能更早发现“开发环境正常、上线才出错”的问题。
自动化测试和日志排查要一起做
测试层面,可以结合:
PHPUnit做单元测试;Selenium做集成测试。
日志层面,要重点盯住这些文件:
- PHP-FPM 日志,例如
/var/log/php8.x-fpm.log - Web 服务器错误日志,例如 Nginx 的
/var/log/nginx/error.log
如果升级后出现 502,优先排查的通常就是 socket 权限和进程管理设置,这两类问题在新旧版本切换时最容易被忽略。
迁移不要一步到位,按风险分阶段推进
旧项目升级最怕“大爆改”。更实际的方式,是把问题按影响范围拆开,先修会导致直接崩溃的部分,再处理性能和维护性问题。
- 优先修致命问题:例如
mysql_*函数、短标签这类会直接影响运行的问题; - 逐步替换旧扩展和旧参数:例如
mcrypt改为openssl,再根据实际情况调整配置参数,如pm.max_requests从 1000 降到 500,以减少内存泄漏风险; - 每改一批就做回归测试:避免兼容问题刚修完,又引入新的业务故障。
按这个顺序推进,升级 PHP-FPM 就不再是一次高风险切换,而是一个可以观察、可以回退、可以逐步收口的迁移过程。







