根本原因是$document_root未正确定义或作用域失效,导致SCRIPT_FILENAME拼接出错;必须确保root指令位于server块、禁用PHP-FPM的doc_root限制,并优先使用$realpath_root$fastcgi_script_name。

为什么 SCRIPT_FILENAME 拼出来的路径总是错的?
根本原因不是文件不存在,而是 Nginx 传给 PHP-FPM 的 SCRIPT_FILENAME 值压根没指向真实文件位置。常见现象是:日志里报 Unable to open primary script: /var/www/html/get.php (No such file or directory),但你 ls -l /var/www/html/get.php 确实存在。
这通常因为 $document_root 变量在 location 块里不可用——它只继承自 server 或 http 块里的 root 指令。如果 root 写在另一个 location 里(比如 location /),那匹配 .php$ 的 location 就拿不到值,$document_root$fastcgi_script_name 就会变成空路径拼接,结果就是乱路径。
- 检查你的 Nginx 配置:确保
root指令写在server块里,而不是只放在某个location /中 - 不要依赖
$document_root在 php location 里“自动生效”,它不跨 location 继承 - 临时验证方法:把
fastcgi_param SCRIPT_FILENAME改成绝对路径硬编码(如/var/www/html$fastcgi_script_name),如果能跑通,就坐实了是$document_root未定义问题
PHP-FPM 的 doc_root 和 Nginx 的 root 必须对齐吗?
不一定,但二者冲突时必出 No input file specified。PHP-FPM 如果配置了 php_value[doc_root](比如在 pool.d/www.conf 里),它会强制把所有请求的脚本路径截断、重写进这个目录下,相当于加了一层路径过滤。
典型冲突场景:Nginx 的 root 指向 /data/app/pub,而 PHP-FPM 的 doc_root 是 /data/app。这时 Nginx 传来的 /data/app/pub/index.php 会被 PHP-FPM 自动转成 /data/app/index.php,自然找不到文件。
- 推荐做法:直接注释或删掉 PHP-FPM pool 配置里的
php_value[doc_root]行,让 PHP 完全信任 Nginx 传来的SCRIPT_FILENAME - 如果必须保留
doc_root(例如多租户隔离),那它的值必须和 Nginx 的root完全一致,末尾不带斜杠,路径大小写也需严格匹配 - 宝塔用户注意:PHP 设置页里勾选了“防跨站”后,底层会自动注入
open_basedir和隐式doc_root限制,关掉它常比调路径更省事
fastcgi_param SCRIPT_FILENAME 应该用哪个变量组合?
优先用 $realpath_root$fastcgi_script_name,次选用 $document_root$fastcgi_script_name。前者会先解析软链接、修正路径,后者只是字符串拼接。
比如你用软链接部署:/www/wwwroot/site → /www/wwwroot/site-v2,Nginx 的 root 指的是软链接路径,但实际文件在目标目录。用 $document_root 会拼出软链接路径下的文件,而 PHP-FPM 可能因权限或挂载限制读不到;$realpath_root 则自动展开为真实路径。
- 确认
fastcgi_params文件里没有覆盖你手动写的SCRIPT_FILENAME—— 它可能自带一行默认配置,把你自己的顶掉了 - 如果你的 Nginx 版本 ≥ 1.19.1,
$realpath_root可用;旧版本请确保root指向的是真实物理路径,而非软链接 - 别用
$script_filename:它是 Nginx 内部变量,仅在 rewrite 后重写阶段有效,在 fastcgi_param 里不可用
宝塔面板下最容易被忽略的三个点
宝塔把很多底层配置封装了,反而容易漏掉关键环节。出 No input file specified 时,先查这三项:
- 网站根目录设置是否指向含
index.php的子目录(如 Laravel 的public、ThinkPHP 的public、Magento 的pub)—— 错设成项目根目录会导致 Nginx 的root值错误,连带SCRIPT_FILENAME全盘失效 - PHP 版本设置页里的“防跨站”开关是否开着,且
open_basedir路径里没包含运行时需要的目录(如runtime、storage、/tmp) - 伪静态规则是否干扰了 PHP 路由,比如 ThinkPHP 的
think规则或 Laravel 的laravel规则里漏写了try_files $uri $uri/ /index.php?$query_string;,导致 .php 请求没进到 PHP-FPM,而是被当成静态文件处理
路径同步这事看着简单,实际是 Nginx 和 PHP-FPM 之间最脆弱的握手环节。变量名差一个下划线、路径少一个字符、配置落错块级作用域,都会让整个链路静默失败。动手前先看一眼 error.log 里那句真实的 “Unable to open primary script”,它比浏览器上的“No input file specified”更有指向性。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











