Nginx 多个位置,每个位置都有自己的根

Nginx multiple locations each with its own root

server {
  listen 80;
  server_name ~^(?<cc>.+?).local.solar.bc.digital$;
  client_max_body_size 1m;

  root /home/vagrant/sites/$cc/_www/;
  index  index.html index.htm index.php;
  error_page 404 /index.php;
  access_log /var/log/nginx/$cc-access.log;
  error_log /var/log/nginx/$cc-error.log;
  charset utf-8;
  sendfile off;

  location / {
    root /home/vagrant/sites/$cc/_www/php/;
    try_files $uri $uri/ /index.php?$query_string;
  }

  location /shop/ {
    # root /home/vagrant/sites/$cc/_www/bcshop/;
    try_files $uri $uri/ /index.php?$query_string;
  }

  location ~ \.php$ {
    fastcgi_index index.php;
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    include /etc/nginx/fastcgi_params;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_param SCRIPT_FILENAME $request_filename;
    fastcgi_param APP_ENV dev;
    fastcgi_param PLATFORM_ENVIRONMENT local;
    fastcgi_read_timeout 300;
    fastcgi_buffers 16 16k;
    fastcgi_buffer_size 32k;
  }

  location ~ /\.ht {
    deny all;
  }
}

好的,鉴于上面的配置。如果您看到我正在尝试做的事情,就知道它不起作用!

一些细节:

  1. 我有一般的 'root',因为没有我会出错。
  2. 这是在用于开发的本地虚拟机上。我们在本地有一个部署工具,对于每个项目(参考上面配置中的 $cc 变量),它最多可以部署两个应用程序。不一定都为每个项目部署。第一个应用程序部署在 /home/vagrant/sites/$cc/_www/php,第二个应用程序部署在 /home/vagrant/sites/$cc/_www/bcshop(但我可以做到 shop - 你会从配置中看到原因)
  3. Drupal 上的两个应用程序 运行,因此加载方式相同。我根本无法让它们工作。对于我尝试过的大多数小变体,我都找不到文件。
  4. 当我将第二个应用程序放在 /home/vagrant/sites/$cc/_www/shop(而不是 /home/vagrant/sites/$cc/_www/bcshop)时,我可以加载它的主页,但没有别的。
  5. 当我忽略第二个应用程序并专注于第一个应用程序时,我可以简单地将通用根设置为 /home/vagrant/sites/$cc/_www/php 并从位置 / 中删除本地根。这样可行。但是当它被指定为本地根时它不会。在这种情况下,实际上,我在日志中收到此错误:"FastCGI sent in stderr: "Primary script unknown"while reading response header from upstream"。这仅适用于第一个应用程序。
  6. 如果您想知道为什么将通用根设置为该值,那是因为如果通用根无法针对匹配的位置进行验证,我会在日志中收到错误消息。有道理吗?

我想我已经总结了几乎所有我所做的事情。

想法?

我根本不是 nginx 专家,所以我在文档和此处回答的其他问题的帮助下,通过反复试验。但到目前为止,没有喜悦。

谢谢大家

您在 _www/bcshop/ 路径和 _www/php/ 路径中都有 PHP 个文件。如果您想为两个应用程序使用一个公共 location ~ \.php$,则每个应用程序的 URI 需要分别以 /bcshop/php 作为前缀。也就是说,两个应用程序 出现在 到 运行 的子目录中。

我怀疑您想对一个应用程序使用 /shop 前缀,而对另一个应用程序使用 / 前缀。在这种情况下,将需要两个 location ~ \.php$ 块。

来自服务器根目录的 运行 个应用程序:

root /home/vagrant/sites/$cc/_www/php;
location / {
    try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
    try_files $uri /index.php;

    include /etc/nginx/fastcgi_params;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_param SCRIPT_FILENAME $request_filename;
    ...
}

还有一个应用程序 运行 的 URI 前缀为 /shop 但位于子目录 _www/bcshop:

location ^~ /shop {
    rewrite ^/shop(?:/(.*))?$ /bcshop/ last;
}

location ^~ /bcshop/ {
    internal;
    root /home/vagrant/sites/$cc/_www;

    try_files $uri /shop/index.php?$query_string;

    location ~ \.php$ {
        try_files $uri /shop/index.php;

        include /etc/nginx/fastcgi_params;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        ...
    }
}

^~ 修饰符确保 location 块优先于上面的正则表达式位置块。有关详细信息,请参阅 this document

虽然外部URI前缀是/shop,但它被悄悄重写为/bcshop,这样我们就可以继续使用root指令。有一个 alias 指令,但它有 issues with try_files 并且很难与 PHP.

一起使用

根据@RichardSmith 的回答,我提出了自己的变体(工作正常)。仅仅因为重复 location ~ \.php$ 的块让我头疼。

...
...
root /home/vagrant/sites/$cc/_www/;
...
...
location / {
  set $actual_root /home/vagrant/sites/$cc/_www/php/;
  set $fastcgi_index /index.php;
  root $actual_root;
  try_files $uri $uri/ $fastcgi_index?$query_string;
}

location /shop/ {
  set $actual_root /home/vagrant/sites/$cc/_www/;
  set $fastcgi_index /shop/index.php;
  root $actual_root;
  try_files $uri $uri/ $fastcgi_index?$query_string;
 }

location ~ \.php$ {
  root $actual_root;
  fastcgi_index $fastcgi_index;
  fastcgi_split_path_info ^(.+\.php)(/.*)$;
  include /etc/nginx/fastcgi_params;
  fastcgi_pass 127.0.0.1:9000;
  fastcgi_param SCRIPT_FILENAME $actual_root/$fastcgi_script_name;
  fastcgi_param PATH_INFO $fastcgi_path_info;
  fastcgi_param APP_ENV dev;
  fastcgi_param PLATFORM_ENVIRONMENT local;
  fastcgi_read_timeout 300;
  fastcgi_buffers 16 16k;
  fastcgi_buffer_size 32k;      
}

...
...