你这条补充很关键:版本确认完,还得确认补丁是否真的装到了包里,这一步不能省。我再补充三个容易出错的地方。
查包的时候先分清用的是哪个源。 如果用的是 Debian/Ubuntu 官方 security 源,版本号会带 +deb11uX;但如果装的是 ondrej/sury 源,版本号形如 7.4.33-15+0~2024xxxx...,根本没有 +debXu 后缀。如果只按 +debXu 去 grep,会误判成“没打补丁”。更稳的写法是 dpkg-query -W -f='${Package} ${Version}\n' 'php7.4-*',再看 apt-cache policy php7.4-fpm 输出的源优先级。
changelog 可能不存在。 如果安装时启用了 --no-install-recommends,或者 doc 目录被裁掉,zcat 就会直接报错。可以直接用 zgrep -i cve /usr/share/doc/php7.4-*/changelog.Debian.gz | tail -30 查找 CVE 编号,这比通读 changelog 快得多;再不行,就用 apt changelog php7.4-fpm。
Remi 在 RHEL8+ 上还要先处理 module 流。 系统自带的 php module 会覆盖 remi,必须执行 dnf module reset php(或 disable),否则即使启用了 --enablerepo=remi-php74,装上的还是旧包。改完后,再用 dnf repoquery --repo=remi-php74 php-fpm 确认候选版本对得上。
user_ini.filename 改成 pool 级,我完全同意,比全局置空干净得多。补充一点:它不是用 ini_set 能改的,所以必须写在 pool 配置里;验证时要在该 pool 建一个探测页,打印 ini_get('user_ini.filename'),不要指望 php -i 能看出来。
升级 8.x 的断点我再补一个最容易造成线上故障的问题:mysqli 从 8.1、PDO 从 8.0 起默认错误模式改成抛异常,老代码里 $result === false 那套判断会全部失效,直接抛致命错误。这条 Rector 未必能扫出来,得手动 grep mysqli_query、->query( 的返回值判断。
reload 那条也对,再提醒一点:老 worker 受 worker_shutdown_timeout 控制,默认是 0,也就是不超时,长连接会挂很久。验证前先用 ps -o pid,lstart,args -C php-fpm 看老 worker 退没退,请求带上真实域名的 Host 头,别打 127.0.0.1 落到默认 server 块上去。