根本原因是Nginx错误解析PATH_INFO导致PHP-FPM收到空或非法SCRIPT_FILENAME而返回空响应,Nginx判定上游失败抛出502;常见于正则匹配失败使PATH_INFO为空、军哥LNMP enable-php.conf硬伤、宝塔默认规则未判空等场景。

为什么ThinkPHP伪静态一开就502
根本原因不是“伪静态没配好”,而是Nginx把 PATH_INFO 解析错了,导致PHP-FPM拿到空或非法的 SCRIPT_FILENAME,直接返回空响应,Nginx判定为上游失败,抛出502。
ThinkPHP依赖 PATH_INFO 拆解URL路由(比如 /index/user/list → index.php + /user/list),但Nginx默认不传递该变量,且常见正则写法(如 location ~ \.php(.*)?$)在提取 $1 时极易因匹配失败而赋空值,进而让 fastcgi_param PATH_INFO $1 变成 PATH_INFO "",触发FPM内部路径校验失败。
- 错误日志里常出现
FastCGI sent in stderr: "Primary script unknown"或"No input file specified" - 用
curl -I http://yoursite.com/index.php/s/1测试,如果直接返回502,基本可锁定是PATH_INFO传递问题 - 宝塔用户尤其要注意:其自动生成的伪静态规则默认启用正则匹配,但未做
$1非空判断,风险极高
try_files模式绕过PATH_INFO更稳妥
不依赖正则提取 PATH_INFO,改用查询字符串方式传参,由ThinkPHP自己解析 $_SERVER['QUERY_STRING'],彻底避开Nginx路径解析歧义。
在server块内替换原有PHP location,只保留两段:
立即学习“PHP免费学习笔记(深入)”;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
}
- 必须删掉旧的
location ~ \.php(.*)?$块,否则会冲突(Nginx优先匹配最长正则,旧规则仍生效) -
try_files中的$query_string会把完整查询串(如s=user/list&id=1)透传给PHP,ThinkPHP 5.0+原生支持 - 若用ThinkPHP 6.x,确认
config/app.php中'url_route_must' => false,避免强制PATH_INFO校验
LNMP一键包用户要重修enable-php.conf
军哥LNMP的 /usr/local/nginx/conf/enable-php.conf 里那段PATH_INFO提取逻辑有硬伤:if条件匹配失败时,$fastcgi_script_name2 为空,后续 SCRIPT_FILENAME 就拼出 /var/www//index.php 这种非法路径,直接502。
打开该文件,找到类似这段:
if ($fastcgi_script_name ~ "^(.+\.php)(/.+)$") {
set $fastcgi_script_name2 $1;
set $path_info $2;
}
- 把
set $fastcgi_script_name2 $1;改成set $fastcgi_script_name2 $fastcgi_script_name;—— fallback到原始值,不冒险 - 紧接着的
fastcgi_param SCRIPT_FILENAME行,必须改成fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name2; - 删掉所有重复的
fastcgi_param PATH_INFO行,ThinkPHP 5.1+已不强制依赖它
别忽略fastcgi_read_timeout和buffer设置
即使PATH_INFO通了,大文件上传、长事务或慢SQL也可能让PHP-FPM响应超时,Nginx主动断连并返回502,日志里显示 upstream timed out。
- 在PHP location块里加:
fastcgi_read_timeout 300;(单位秒,按业务最长耗时设) - 加大缓冲区:
fastcgi_buffer_size 128k;和fastcgi_buffers 8 128k;,避免响应体过大被截断 - 检查PHP侧:
max_execution_time和post_max_size必须 ≥ Nginx timeout值,否则PHP先杀进程 - 宝塔用户可在网站设置 → 配置修改 → 在“配置文件”末尾追加,不要改全局fastcgi_params
PATH_INFO解析和超时参数是两个独立维度的问题,一个配错就会502,但日志表现相似——得看error.log里那句具体报错,而不是凭感觉调。



















