Nginx 配置 Laravel 一段时间后 出现404 问题

问题描述:

启动 nginx 后可以正常访问,数小时后访问就 404,No input file specified.

access log 里面只有 404 的 log,没有任何错误 log

public目录下面的静态资源可以正常访问

是哪里的问题呢?请教各位大神了。配置参考 https://yii.im/posts/the-righ...

配置如下:

index index.html index.htm index.php;
root /apps/www/lavarel_test/public/;

access_log  logs/laravel_test.log;

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

location ~ \.php$ {

    #client_max_body_size 5m;
    include  fastcgi_params;
    fastcgi_pass   unix:/tmp/php-cgi.sock;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
}
阅读 4.1k
1 个回答

排查过程:

排查各种路径问题和log,都没找到原因。

GG搜索一轮,提示说可以开启Nginx的debug信息进行查看

#nginx.conf
error_log  /home/wwwlogs/nginx_error.log  debug;

在访问出现No input file specified.时,产生一个error级的日志:

FastCGI sent in stderr: "PHP message: PHP Warning:  Unknown: open_basedir restriction in effect. 
File(/home/apps/www/lavarel_test/public/index.php) is not within the allowed path(s): 
(/apps/www/default/:/tmp/:/proc/) in Unknown on line 0

我就纳闷了,上面的Laravel的Nginx配置里面没有配置这个,php.ini和web目录下面都没有设置open_basedir,怎么会出现了这个限制。

/apps/www/default 是已存在站点的其中一个的根目录,查了该站点的配置,发现其中使用了fastcgi.conf文件:

root /apps/www/default/;

access_log  logs/default.log;

location ~ .*\.php.* {

    include fastcgi.conf;
    client_max_body_size 5m;

    # set PATH_INFO, SCRIPT_FILENAME, SCRIPT_NAME
    set $fastcgi_script_name2 $fastcgi_script_name;

    if ($fastcgi_script_name ~ "^(.+\.php)(/.+)$") {
            set $fastcgi_script_name2 $1;
            set $path_info $2;
    }

    fastcgi_param   PATH_INFO $path_info;
    fastcgi_param   SCRIPT_FILENAME   $document_root$fastcgi_script_name2;
    fastcgi_param   SCRIPT_NAME   $fastcgi_script_name2;
    fastcgi_pass    unix:/tmp/php-cgi.sock;
    fastcgi_index   index.php;

}

而Laravel项目使用的是fastcgi_params文件,对比发现,fastcgi.conf比fastcgi_params多了2行:

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/";

分析到这里,问题基本清晰了,default这个站,偶尔会有访问,这里面的就会把open_basedir配置到/apps/www/default/去。

但是也很奇怪,Laravel的Nginx配置里不设置PHP_ADMIN_VALUE,也会被影响到,猜测这个PHP_ADMIN_VALUE是直接影响到每个fastcgi请求里面,待后续有空再研究。

因此,只要把fastcgi_params换成fastcgi.conf就OK了。配置完,重启,页面一片空白……查看nginx的log,又出现了相似的错误:

FastCGI sent in stderr: "PHP message: PHP Warning:  require(): open_basedir restriction in effect. 
File(/home/apps/www/lavarel_test/bootstrap/autoload.php) is not within the allowed path(s): 
(/apps/www/lavarel_test/public/:/tmp/:/proc/) in /home/apps/www/lavarel_test/public/index.php on line 22

可以看到,open_basedir的设置没有问题,但是框架引入的文件在/home/apps目录下面,查看index.php源码发现,用到了PHP的魔术常量:__DIR__

require __DIR__.'/../bootstrap/autoload.php';

由于/apps是一个软连接,指向/home/apps,故这里返回的路径是原始路径。

这里不要以为修改为原始路径就可以了,依然会出现类似的错误,因为框架会引用/home/apps/www/lavarel_test下面各个文件夹的文件。

如果真要修改,就得把根目录设置在项目的根目录:

root /home/apps/www/lavarel_test/

至此,问题基本解决。

总结:

一些版本的Nginx安装完,默认的fastcgi.conf文件里面,会包含一句

fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/";

这个是LNMP环境下,通过Nginx配置防止PHP跨站,跨目录访问的安全设置,通过PHP_ADMIN_VALUE来设置open_basedir来实现。

如果Nginx下有多个站点,其中有上述配置的,会影响没有该配置的其他站点,导致访问路径受限。

另外,像Laravel、ThinkPHP等一些框架,如果根目录配置到public下也需要注意,open_basedir的目录限制是否在项目根目录下,否则一些框架的文件引用会报错。

参考:

thinkphp5部署于Linux中nginx多站点解决方案 – 爱游思
http://wp.iyouths.org/343.html
PHP open_basedir函数导致的一个nginx配置问题 - 知行合一 - SegmentFault 思否
https://segmentfault.com/a/11...

推荐问题
宣传栏