dongzhuifeng1843 2019-05-02 08:03
浏览 468

Nginx选错了$ document_root

On a simple configuration nginx seems to be picking a random configuration file's document root to set as the $_SERVER['DOCUMENT_ROOT'] inside the PHP process it's attempting to fastcgi proxy to.

I've tried numerous configurations to try and scope the problem including nginx's debug log however to no avail

server {
    listen 80;
    server_name domain.co.uk;
    index index.php;
    error_log /var/log/nginx/domain.co.uk.error.log debug;
    access_log /var/log/nginx/domain.co.uk.access.log;
    root /var/www/domain.co.uk;

    location / {
      try_files $uri /index.php$is_args$args;
    }

    location ~ \.php {
      try_files $uri =404;
      fastcgi_split_path_info ^(.+\.php)(/.+)$;
      fastcgi_param SCRIPT_FILENAME /var/www/domain.co.uk/index.php;
      fastcgi_param SCRIPT_NAME $fastcgi_script_name;
      include fastcgi_params;        
      fastcgi_index index.php;
      fastcgi_pass  unix:/dev/shm/php.7.2.sock;        
    }
}

What happens is that the request picks a random other configuration and applies the document root from that to it. THe other configurations tend to have an auto_prepend line in the PHP part of the config that auto_prepends a config.php file to every request. The strange part os that the config.php from another random site (it's never the same site twice in a row) has some includes in it - one of which is an autoloader. The autoloader tries to load a file which does not exist (error below)

2019/05/02 08:37:34 [error] 19105#0: *575827 FastCGI sent in stderr: "PHP message: PHP Fatal error: require(): Failed opening required '/var/www/domain.co.uk/resources/lib/class.autoloader.php' (include_path='.:/usr/share/php') in /var/www/www.anotherdomain.co.uk/config.php on line 84

What this error is saying is that it's prepending the config.php file from /var/www/www.anotherdomain.co.uk/config.php which is ultimately causing the error chain.

I am absolutely lost on how to start debugging this, I've been at it for two whole days and am none the wiser!

As I say, most of the other site configs have the auto_prepend PARAM in the config so my question is really why is nginx picking one of those at random to apply to the config file in question?

If I change fastcgi_params to remove $document_root the problem goes away which tells me that nginx doens't know what the $document_root is at the time of the request for some really strange reason.

Thanks in advance!

  • 写回答

1条回答 默认 最新

  • douzhouqin6223 2019-05-02 09:17
    关注

    The issue you are having is due to a failure to understand how PHP-FPM operates. Each PHP process is long lived and reused, however for performance each process loads in it's ini config (including PHP_VALUE env vars) and any extensions it requires on the first request.

    In your scenario you have two websites sharing the same PHP-FPM pool, lets call these "SiteA" and "SiteB", and each are configured the way you mentioned, using the PHP_VALUE environment variable with separate prepend files.

    1. A user hits SiteA, PHP is not yet initialised, so it loads it's config, and the prepend file loaded and cached for use.
    2. A user now hits SiteB, but now PHP is already initialized, so it continues using the existing loaded configuration, attempting to use SiteA's prepend file.

    If you were to reverse this and hit SiteB first, then forever SiteB's prepend file would be loaded until you restarted the FPM pool.

    To correct this you need to run a separate pool for each website, with a auto_prepend_file for each, ideally configured in the pool's config instead of by setting a Nginx environment variable. This is highly recommended anyway for security as it adds a level of isolation you would otherwise be missing.

    I suggest you follow the guide I made here on an optimal, multi-user secure PHP+Nginx configuration and alter it to your requirements.

    https://www.youtube.com/watch?v=NIwadOtwdaI

    Note: this guide is part of a series from start to finish on how to setup a fully featured HTTP server from scratch, if you need more information check out the prior videos.

    Edit2: Please note that this video needs an update, the usage of try_files is far better then the if usage described in the video. See: https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/

    评论

报告相同问题?

悬赏问题

  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥20 测距传感器数据手册i2c