使用 Nginx + php-fpm 从特定 URI 服务 PHP 应用程序:"Primary script unknown" 错误

Serve PHP App from Particular URI Using Nginx + php-fpm: "Primary script unknown" Error

我正在尝试配置 Nginx 以同时为 Django 应用程序和 Laravel 应用程序提供服务。我的 Django 应用程序正常工作,所以现在我想从 /snipe-it 获取 Laravel 应用程序。

我正在努力处理的 nginx 配置的主要部分在这里:

    location /snipe-it/ {
        alias /var/www/html/public/;
        #try_files $uri $uri/ /index.php$is_args$args;

        location ~* \.php(/|$) {
            try_files $uri $uri/ =404;
            include fastcgi_params;
            fastcgi_pass unix:/run/php/php7.3-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }
    }

index.php文件的实际文件位置是/var/www/html/public/index.php.

尝试访问 http://127.0.0.1/snipe-it/index.php 上的 Laravel 应用程序时,我收到“找不到文件”。日志输出如下所示:

nginx_1        | - -  24/Jun/2020:17:37:40 +0000 "GET /snipe-it/index.php" 404
nginx_1        | 2020/06/24 17:37:40 [error] 17#17: *1 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 172.30.0.1, server: 127.0.0.1, request: "GET /snipe-it/index.php HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.3-fpm.sock:", host: "127.0.0.1"
nginx_1        | 172.30.0.1 - - [24/Jun/2020:17:37:40 +0000] "GET /snipe-it/index.php HTTP/1.1" 404 27 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:77.0) Gecko/20100101 Firefox/77.0" "-"

一切都在一个 docker 容器中,该容器源自使用 Debian buster 的官方 nginx 映像。我相信日志的第一行来自 php-fpm7.3 进程,因为我在 /etc/php/7.3/fpm/pool.d/www.conf 文件中将 access.log 设置为 /proc/self/fd/2。我还将 catch_workers_output 设置为 yes 希望它可以更深入地了解应用程序在哪里寻找 index.php 文件,但它似乎没有。

如果有帮助,index.php 的权限如下所示:

-rw-r--r-- 1 docker www-data 1887 Jun 23 21:13 index.php

我目前 运行 nginx 作为 www-data 用户,php-fpm 作为 www-data 组中的 docker 用户。似乎“未知主脚本”错误可能是由许多问题引起的,因此有关如何深入研究以找到有关问题所在的更多线索的任何提示都会有所帮助。

仅供参考,这是我的完整 nginx conf 文件:

upstream intranet {
    server web:8000;
}

upstream prometheus {
    server prometheus:9090;
}

server {
    listen 80;
    server_name 127.0.0.1;
    root /var/www/html/public;
    index index.php index.html index.htm;

    location /static {
        alias /home/static;
    }

    location /media {
        alias /home/media;
    }

    # Prometheus settings
    location /prometheus/ {
        proxy_pass http://prometheus;
    }

    location /snipe-it/ {
        alias /var/www/html/public/;

        location ~* \.php(/|$) {
            try_files $uri $uri/ =404;
            include fastcgi_params;
            fastcgi_pass unix:/run/php/php7.3-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }
    }

    location / {
        proxy_pass http://intranet;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }
}

根据 nginx ngx_http_fastcgi_module documentation$fastcgi_script_name 内部变量包含请求 URI,或者,如果 URI 以斜杠结尾,则请求 URI 具有由 fastcgi_index 附加到它的指令。当你使用

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

得到一个/snipe-it/script.php传入请求,一个$uri内部变量等于/snipe-it/script.php$document_root$fastcgi_script_name内部变量等于/var/www/html/public/,并且连接的 $document_root$fastcgi_script_name 字符串变为 /var/www/html/public//snipe-it/script.php,这显然会导致文件不存在。你能做的是

    location ~ ^/snipe-it/(?<subpath>.*)$ {
        alias /var/www/html/public/;
        location ~* \.php$ {
            include fastcgi_params;
            fastcgi_pass unix:/run/php/php7.3-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$subpath;
        }
    }

请注意,当您使用 root 指令而不是 alias 时,不会出现此问题。但是,这是不可能的,除非您将 /var/www/html/public 目录重命名为 /var/www/html/snipe-it(您可以使用 root /var/www/html; 而不是 alias /var/www/html/public/;)。