Nginx 连接 PHP-FPM socket 报 "Permission denied" 怎么办?
Nginx connect() to php-fpm.sock failed (13: Permission denied) 的修复:调整 PHP-FPM pool 的 listen.owner/listen.group/listen.mode,让 socket 属主与 Nginx worker 用户匹配,附排查步骤与 FAQ。
这是 PHP-FPM 的 Unix socket 文件属主/权限与 Nginx worker 用户不匹配导致的。标准修法:编辑 PHP-FPM 的 pool 配置(pool.d/www.conf),把 listen.owner、listen.group 设为 Nginx 的运行用户(如 www-data),listen.mode = 0660,然后重启 PHP-FPM。
完整修复步骤
1. 确认两边各是谁
# Nginx worker 以谁运行
ps aux | grep "nginx: worker" | head -1 # 常见 www-data 或 nginx
# PHP-FPM socket 在哪、属主是谁
grep '^listen' /etc/php/*/fpm/pool.d/www.conf
ls -l /var/run/php/php*-fpm.sock
典型问题现场:socket 属主是 root:root、权限 0660——Nginx 的 www-data 用户当然连不上。
2. 修改 pool 配置
编辑 /etc/php/8.x/fpm/pool.d/www.conf:
listen = /var/run/php/php8.2-fpm.sock
listen.owner = www-data # 与 Nginx worker 用户一致
listen.group = www-data
listen.mode = 0660 # socket 权限:属主+组可读写
(RHEL/CentOS 上 Nginx 用户通常是 nginx,两处都换成它。)
3. 重启生效并验证
sudo systemctl restart php8.2-fpm
ls -l /var/run/php/php8.2-fpm.sock
# srw-rw---- 1 www-data www-data ... ← 属主对了
页面从 502 Bad Gateway 恢复正常即修复完成。
其他可能成因(改完没用时继续查)
- socket 路径不一致:Nginx 里
fastcgi_pass unix:/var/run/php5-fpm.sock;写的路径和 pool 里listen的实际路径不符(系统升级 PHP 版本后最常见——php5-fpm.sock早已变成php8.2-fpm.sock)。改 Nginx 配置指到正确路径。 - SELinux(CentOS/RHEL):上下文不对照样拒绝。
audit2allow分析拒绝记录,或给 httpd 开httpd_can_network_connect类布尔值。 - socket 目录权限:
/var/run/php/目录本身要允许 Nginx 用户进入。
观测云对照
502 是用户最先看到、运维最后知道的错误之一。把 Nginx error.log 采集到观测云,对 connect() to unix:... failed 设关键字告警,PHP-FPM 重启、socket 权限漂移导致的 502 在分钟级就能通知到人;访问日志里按 URI 聚合 502 分布,能快速圈定影响面。
常见问题(FAQ)
Q:直接把 listen.mode 改成 0666 行不行?
A:能跑但不好——任何本地用户都能连你的 PHP-FPM 执行 PHP 代码。正确答案是 owner/group 对齐 + 0660。
Q:为什么升级 PHP 之后突然报这个错?
A:新版本默认 pool 配置可能重置了 listen 参数,或 socket 路径带了新版本号。升级后先比对 www.conf 与 Nginx 的 fastcgi_pass。
Q:不用 socket,改 TCP(127.0.0.1:9000)能绕过吗?
A:能——listen = 127.0.0.1:9000 + fastcgi_pass 127.0.0.1:9000; 就不存在文件权限问题,还方便容器间通信;代价是略高的开销和端口管理。本机通信 socket 仍是首选。