Ubuntu 22.04 上 nginx 和 php-fpm 8.1 分开装,nginx 的 fastcgi_pass 指向 unix:/run/php/php8.1-fpm.sock,访问 PHP 页面一律 502,php-fpm 日志里是 failed to open socket,把地址换成 127.0.0.1:9000 立刻正常。

一开始怀疑是「/run/php 目录权限是 700,nginx 连目录都进不去」,查了一圈,方向不对。

这类报错背后常见的原因有几处,逐个排除就行。socket 文件的属组是 www-data,nginx 进程跑在 nginx 用户下。少数情况下是php-fpm 的 listen.owner 和 listen.group 没配,默认落到 root。

不容易想到的是,AppArmor 拦住了 nginx 访问 /run/php 下的文件。

第一件事是看 socket 的实际属主和权限

ls -l /run/php/php8.1-fpm.sock && namei -l /run/php/php8.1-fpm.sock

随后把 owner 和 group 写进池配置

grep -nE 'listen.(owner|group|mode)' /etc/php/8.1/fpm/pool.d/www.conf

然后改完重启 php-fpm 让 socket 重建

systemctl restart php8.1-fpm && ls -l /run/php/

剩下的就是确认 AppArmor 有没有相关拒绝记录

dmesg | grep -i apparmor | tail -5

同事提醒我看一下最近一次发布,时间点确实对得上。

命令输出我都留了记录,免得改完记不清原来的值。

别只看报错消失,验证要多做一步。浏览器访问 PHP 页面返回 200,php-fpm 日志里没有 failed to open socket,nginx 与 fpm 之间的连接数正常。

容易忽略的是,socket 比 TCP 少一层协议栈也省端口,但要求两个进程在同一台机器且权限对齐;升级 PHP 版本后 socket 路径会变,别忘同步 fastcgi_pass。这类问题最好一次改到位,反复小改反而容易把原因搅混。

作者 9823189