如何解决nginx+php报错“No input file specified”

      访问: 6,122 次      评论    

2014/07/02 21:53:02 [error] 4952#0: *8 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstr eam, client: 180.180.180.180, server: localhost, request: "GET /info.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "100.100.100.100"

nginx+PHP,访问PHP页面显示空白并提示“No input file specified”,nginx错误日志中显示"Primary script unknown" 。这实际上是PHP在display_errors设置为off时,PHP报出的错误。在PHP默认安装下,会将错误输出到stderr或stdout、然后被nginx捕获并记录在error.log中。其根本原因是PHP无法找到nginx告诉它的相应文件,有一些原因可以导致这个问题,如下。

1、给PHP传递了错误的路径

大多数原因是初学者参考网上google的文章来配置导致的。Nginx通过 SCRIPT_FILENAME 这个 fastcgi_param 的值来告诉PHP需要执行的文件。网上大多数的文章将这个参数的值设置为 $document_root$fastcgi_script_name ,有时这样配置还是为了解决"No input file specified" 问题的。但是这会导致路径被“写死”,突然有一天你发现问题出现了。

原因在于nginx有三级配置继承关系:三个层次的区块分别为http、server 和 location,是父子的关系。nginx配置里的命令向下继承,但不会向上继承或交叉。比如你在一个 location中定义了一些东西,是不会应用到其他location中的。

典型的一些初学者,在 location / 中定义 index 和 root ,因为网上的文章是这么教的。当再使用 $document_root 来定义SCRIPT_FILENAME 时,root 并没有真正被定义,因此 SCRIPT_FILENAME 的值仅仅变成了URI,导致PHP找不到该文件。

简单的解决办法是在 server 或 http 区块中定义 root 。

2、不正确的文件权限

当我告诉他你的权限设置不正确时,大多数人都不相信我。他们盯着脚本文件的权限设置,PHP用户有读取权限啊!?很遗憾,这表现出他对Unix用户权限缺乏理解。PHP的启动用户不仅需要脚本文件的读权限,还需要能进入到脚本文件所在的目录(及上层目录),这就需要PHP用户拥有这些目录的执行权限。举一个例子:

说你在 /var/www 目录下有一个 index.php 的脚本文件,需要PHP用户对 /var/www/index.php 有读权限,且需要对 /var 和 /var/www 目录有执行权限。

我就遇到过一次新装的Debian nginx+php环境,在将PHP用户加入到 $document_root 目录拥有者的用户组后,因为没有重启 php-fpm 而导致的权限没有生效问题,查了半天原因。

3、使用 Alias 和 $document_root

将 SCRIPT_FILENAME 定义为 $document_root$fastcgi_script_filename 的现象相当普遍。然而 $document_root 并不适用alias指令,从而导致传递了错误的路径。建议将 SCRIPT_FILENAME 定义为如下:

fastcgi_param SCRIPT_FILENAME $request_filename;

这样配置也适用alias指令从而确保了正确的路径传递。$request_filename 实际就是代表 document_root(或 alias)+ request URI 。

4、Chrooted环境

如果你的PHP运行在chrooted环境下、而nginx没有,那么它们基本上有两个不同的root目录,nginx传递给PHP的脚本文件的路径,是不会被解释到真实的文件上去的。一个简单的例子如下:

说你试图访问 phpinfo.php 文件,nginx在你定义的root 目录下找到它:/home/user/public_html/phpinfo.php 。
PHP进程出于安全原因被限制只能访问user的目录,于是PHP认为该服务器的root目录是 /home/user 。所以当nginx报告文件的路径后,PHP会在 /home/user/home/user/public_html/phpinfo.php 下查找该文件。

所以,要么让 nginx和PHP 都处于相同的 chroot 环境下,要么在fastcgi pass to PHP前 rewrite internal URI。

5、open_basedir 限制

PHP在php.ini 中可以设置选项 open_basedir 来限制访问文件的目录在特定位置下,检查一下这个配置项看看。

6、SCRIPT_NAME vs SCRIPT_FILENAME

Fastcgi 有两个非常相似的参数,确保你没有混淆 SCRIPT_NAME 和 SCRIPT_FILENAME 。SCRIPT_FILENAME 告诉fastcgi 要执行的脚本所在的位置,而 SCRIPT_NAME 仅仅告诉脚本的名字。

参考文章:

原文地址:HOW TO SOLVE “NO INPUT FILE SPECIFIED” WITH PHP AND NGINX

添加新评论