在chroot之外的nginx下的chroot下的fastcgi下运行php时,“没有指定input文件”

我有一个在Ubuntu 14.04上运行的nginx/1.4.6 ,但是在一个chroot Ubuntu 9.10 (Karmic Koala)里面有一个php/5.2.10的场景。

我的问题是,所有的PHP文件请求导致恐惧的“ No input file specified.

我把这个站点存放在chroot里面,所以它可以从chroot jail里的php和jail以外的nginx里读取。

 From nginx' point of view: /var/chroot/karmic/var/www/domains/dummysite/web: . www-data:www-data drwxr-xr-x index.php www-data:www-data -rw-r--r-- test.jpg www-data:www-data -rw-r--r-- 

并在chroot里面

 From php's point of view: /var/www/domains/dummysite/web: . www-data:www-data drwxr-xr-x index.php www-data:www-data -rw-r--r-- test.jpg www-data:www-data -rw-r--r-- 

index.php是死的简单!

 <?php echo '<h1>Hello World</h1> Foo bar...'; ?> 

我已经用lighttpd的spawn-fcgi用这个命令启动了php-fcgi:

 LANG=C chroot /var/chroot/karmic /usr/bin/spawn-fcgi -C 12 -a 127.0.0.1 -p 9000 -u www-data -g www-data -f /usr/bin/php5-cgi -P /var/run/fastcgi-php.pid 

Nginx可以成功地为静态test.jpg服务,但php-fcgi无法读取index.php

 # /etc/nginx/site-enabled/dummysite -> /etc/nginx/site-available/dummysite: server { listen 80; root /var/chroot/karmic/var/www/domains/dummysite/web; server_name dummysite.wtf; location / { try_files $uri $uri/ /index.php?q=$uri&$args; index index.php index.html; allow all; } location ~ ^/index\.php { fastcgi_pass 127.0.0.1:9000; fastcgi_intercept_errors on; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param SCRIPT_FILENAME /var/www/domains/dummysite/web$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT /var/www/domains/dummysite/web; include fastcgi_params; } } 

据我所知,这应该是正确的语法。 我也尝试了一些变化,如$document_root$fastcgi_script_name ,没有SCRIPT_NAMEDOCUMENT_ROOT设置和SCRIPT_FILENAME相对于DOCUMENT_ROOTserver块内的root

我没有在php中设置的open_basedir限制。

尽pipe在php和nginx中启用了最大日志loggingfunction,但是在php.log,nginx.error.log或dummysite.wtf.error.log中都没有可用的信息。

我直接使用cgi-fcgi实用程序直接连接到php-fcgi,这是我得到的响应:

 env -i SCRIPT_NAME=index.php DOCUMENT_ROOT=/var/www/domains/dummysite/web SCRIPT_FILENAME=/var/www/domains/dummysite/web/index.php QUERY_STRING= REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000 Status: 404 Not Found X-Powered-By: PHP/5.2.10-2ubuntu6 Content-type: text/html No input file specified. 

所有与SCRIPT_FILENAME设置为相同的结果适用

  • 的index.php
  • /web/index.php
  • /dummysite/web/index.php
  • /domains/dummysite/web/index.php
  • /www/domains/dummysite/web/index.php
  • /var/www/domains/dummysite/web/index.php
  • /karmic/var/www/domains/dummysite/web/index.php
  • /chroot/karmic/var/www/domains/dummysite/web/index.php
  • /var/chroot/karmic/var/www/domains/dummysite/web/index.php

我已经尝试了各种DOCUMENT_ROOT

TL; DR

 /etc/nginx/sites-enabled/dummysite -> /etc/nginx/sites-available/dummysite ... location ~ \.php { root /var/www/domains/dummysite/web; fastcgi_pass 127.0.0.1:9000 include fastcgi_params; } ... 

 /etc/nginx/fastcgi_params ... fastcgi_param SCRIPT_NAME $document_root$fastcgi_script_name; ... 

解决scheme长

好吧,这就是我解决这个问题的方法(我认为这可能对某人来说很方便)。 由于php-cgi不是很详细,我使用strace来捕获php的文件操作到磁盘。

  sudo strace -p <pid-of-first-php-process> -p <pid-of-2nd-php> ... -p <pid-of-nth-php> -e trace=all -s 4096 

然后我直接调用php-fcgi:

 env -i SCRIPT_NAME=index.php DOCUMENT_ROOT=/var/www/domains/dummysite/web SCRIPT_FILENAME=/var/www/domains/dummysite/web/index.php QUERY_STRING= REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000 

而strace中有趣的线条是

 [pid 24822] read(3, "\v\tSCRIPT_NAMEindex.php\r\33DOCUMENT_ROOT/var/www/domains/dummysite/web\17%SCRIPT_FILENAME/var/www/domains/dummysite/web/index.php\f\0QUERY_STRING\16\3REQUEST_METHODGET\0", 152) = 152 [pid 24822] lstat("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 [pid 24822] lstat("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 [pid 24822] lstat("/var/www/domains", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 [pid 24822] lstat("/var/www/domains/dummysite", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 [pid 24822] lstat("/var/www/domains/dummysite/web", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 [pid 24822] lstat("/var/www/domains/dummysite/web/index.php", {st_mode=S_IFREG|0644, st_size=31, ...}) = 0 [pid 24822] open("/index.php", O_RDONLY) = -1 ENOENT (No such file or directory) 

好的,很清楚,它成功地尝试了lstat [...]/web/index.php (它具有正确的0644权限),但它试图打开/index.php 。 这导致我尝试SCRIPT_NAME ,瞧!

 env -i SCRIPT_NAME=/var/www/domains/dummysite/web/index.php DOCUMENT_ROOT=/var/www/domains/dummysite/web SCRIPT_FILENAME=/var/www/domains/dummysite/web/index.php QUERY_STRING= REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000 X-Powered-By: PHP/5.2.10-2ubuntu6 Content-type: text/html <h1>Hello World!</h1> Foo bar... 

所以,我的第一个问题是,我的nginxconfiguration应该读取

  fastcgi_param SCRIPT_NAME /var/www/domains/dummysite/web$fastcgi_script_name; # see what i did here ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

老实说; 我不知道这是为什么。 我以为SCRIPT_NAME的目的不是指向这个文件,而只是指出这个文件的名字。 但我想我一定误解了它的目的。

但是,不幸的是,我的问题还没有结束。 对于当我试图curl http://dummysite.wtf/ ,它仍然说No input file specified.

所以,再次,抢救!

 [pid 24819] read(3, "\r\33DOCUMENT_ROOT/var/www/domains/dummysite/web\17%SCRIPT_FILENAME/var/www/domains/dummysite/web/index.php\v%SCRIPT_NAME/var/www/domains/dummysite/web/index.php\f\0QUERY_STRING\16\3REQUEST_METHODGET\f\0CONTENT_TYPE\16\0CONTENT_LENGTH\0177SCRIPT_FILENAME/var/chroot/karmic/var/www/domains/dummysite/web/index.php\v\nSCRIPT_NAME/index.php\v\1REQUEST_URI/\f\nDOCUMENT_URI/index.php\r-DOCUMENT_ROOT/var/chroot/karmic/var/www/domains/dummysite/web\17\10SERVER_PROTOCOLHTTP/1.1\21\7GATEWAY_INTERFACECGI/1.1\17\vSERVER_SOFTWAREnginx/1.4.6\v\tREMOTE_ADDR127.0.0.1\v\5REMOTE_PORT46644\v\tSERVER_ADDR127.0.0.1\v\2SERVER_PORT80\v\nSERVER_NAMEdummysite.wtf\17\3REDIRECT_STATUS200\17\vHTTP_USER_AGENTcurl/7.35.0\t\nHTTP_HOSTdummysite.wtf\v\3HTTP_ACCEPT*/*\0\0\0\0\0\0", 672) = 672 

然后就是答案了, SCRIPT_NAMESCRIPT_FILENAMEDOCUMENT_ROOT出现两次,第一次是正确的,第二次是不正确的值。 事实certificate,在nginx server块中include fastcgi_params指令将自己插入这些variables,并且当我把这个include语句放在我的location块中时,它实际上覆盖了我以前的设置。

这是我如何解决这个问题:

 /etc/nginx/sites-enabled/dummysite -> /etc/nginx/sites-available/dummysite ... location ~ \.php { root /var/www/domains/dummysite/web; # ^ This line will set the $document_root variable used later on fastcgi_pass 127.0.0.1:9000 include fastcgi_params; } ... 

在包含的fastcgi_params文件中,我改变了这一行

 /etc/nginx/fastcgi_params ... fastcgi_param SCRIPT_NAME $document_root$fastcgi_script_name; # This is needed for chroot to work -> ^$document_root^ ... 

最后, 光荣的成功

 $ curl http://dummysite.wtf <h1>Hello World!</h1> Foo bar... 

这是一种在现代软件(如ubuntu 14.04 LTS和nginx 1.4.x)之上运行一个非常老的php版本的方法:-)