Nginx 1 FastCGI 在 stderr 中发送:“主脚本未知”

We0*_*We0 107 nginx php-fpm

我第一次使用 Nginx,但我对 Apache 和 Linux 非常熟悉。我正在使用一个现有的项目,当我试图查看 index.php 时,我得到一个 404 文件未找到。

这是 access.log 条目:

2013/06/19 16:23:23 [error] 2216#0: *1 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 127.0.0.1, server: localhost, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "www.ordercloud.lh"
Run Code Online (Sandbox Code Playgroud)

这是网站可用的文件:

server {
    set $host_path "/home/willem/git/console/www";
    access_log  /www/logs/console-access.log  main;

    server_name  console.ordercloud;
    root   $host_path/htdocs;
    set $yii_bootstrap "index.php";

    charset utf-8;

    location / {
        index  index.html $yii_bootstrap;
        try_files $uri $uri/ /$yii_bootstrap?$args;
    }

    location ~ ^/(protected|framework|themes/\w+/views) {
        deny  all;
    }

    #avoid processing of calls to unexisting static files by yii
    location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
        try_files $uri =404;
    }

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php {
        fastcgi_split_path_info  ^(.+\.php)(.*)$;

        #let yii catch the calls to unexising PHP files
        set $fsn /$yii_bootstrap;
        if (-f $document_root$fastcgi_script_name){
            set $fsn $fastcgi_script_name;
        }

        fastcgi_pass   127.0.0.1:9000;
        include fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fsn;

        #PATH_INFO and PATH_TRANSLATED can be omitted, but RFC 3875 specifies them for CGI
        fastcgi_param  PATH_INFO        $fastcgi_path_info;
        fastcgi_param  PATH_TRANSLATED  $document_root$fsn;
    }

    location ~ /\.ht {
        deny  all;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的 /home/willem/git/console 归 www-data:www-data(我的网络用户运行 php 等)所有,出于沮丧,我给了它 777 权限......

我最好的猜测是配置有问题,但我无法弄清楚......

更新 所以我把它移到/var/www/并使用了一个更基本的配置:

server {
    #listen   80; ## listen for ipv4; this line is default and implied
    #listen   [::]:80 default ipv6only=on; ## listen for ipv6

    root /var/www/;
    index index.html index.htm;

    # Make site accessible from http://localhost/
    server_name console.ordercloud;

    location / {
        root           /var/www/console/frontend/www/;
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  /var/www;
            include        fastcgi_params;
    }

    location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
            try_files $uri =404;
        }

    location /doc/ {
        alias /usr/share/doc/;
        autoindex on;
        allow 127.0.0.1;
        deny all;
    }

}
Run Code Online (Sandbox Code Playgroud)

另外,如果我打电话,localhost/console/frontend/www/index.php我会得到 500 PHP,这意味着它在那里服务。它只是不在 console.ordercloud 之外提供服务...

Fle*_*der 111

错误消息“主脚本未知”几乎总是SCRIPT_FILENAMEnginxfastcgi_param指令中的错误设置有关(或不正确的权限,请参阅其他答案)。

您在if第一次发布的配置中使用了。那么现在应该是众所周知的,如果是邪恶的并且经常会产生问题。

root在位置块中设置指令是不好的做法,当然它有效。

您可以尝试以下操作:

server {
    location / {
        location ~* \.php$ {
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_pass 127.0.0.1:9000;
            try_files $uri @yii =404;
        }
    }
    location @yii {
        fastcgi_param SCRIPT_FILENAME $document_root$yii_bootstrap;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,上述配置未经测试。您应该nginx -t在应用它之前执行以检查 nginx 可以立即检测到的问题。

  • 对于那些不完全理解变量可能出错的人:将以下内容添加到主要的 Nginx `http` 部分:`log_format scripts '$document_root$fastcgi_script_name > $request';`(或任何你提供给 SCRIPT_FILENAME 的内容) ,和你的`服务器`:`access_log /var/log/nginx/scripts.log scripts`。重新加载并查看您的新脚本日志;) (19认同)
  • yii_bootstrap 是什么? (5认同)
  • 在哪里可以了解更多有关在 location 中设置“root”的不良做法的信息? (3认同)
  • 这为我解决了;我不知道您必须在 $document_root 前面加上前缀,我认为它会根据 root 自动执行此操作。 (2认同)
  • 是的,当然:https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#root-inside-location-block (2认同)

Wil*_*ell 59

这不是总是SCRIPT_FILENAME是错误的。
也可能是PHP 以错误的用户/组身份运行

这个例子是特定于Mac OS X 的,根据我的经验,它是最麻烦的设置(相比之下 Debian 很容易) - 我刚刚从 PHP 5.6 升级到 7.0,使用自制软件和优秀的 josegonzalez 包。

问题是创建了配置文件的新副本。

主配置文件是/usr/local/etc/php/7.0/php-fpm.conf,但请注意末尾的 Pool Definitions部分,其中包含整个子目录。

include=/usr/local/etc/php/7.0/php-fpm.d/*.conf

php-fpm.d有一个www.conf文件。默认情况下,它具有:

user = _www
group = _www
Run Code Online (Sandbox Code Playgroud)

在 OS X 上,您可能需要将其更改为:

user = [your username]
group = staff
Run Code Online (Sandbox Code Playgroud)

(您应该会发现这与ls -lh您的 document_root匹配)

不幸的是,如果没有此更改,您仍会在 Nginx 错误日志中看到此信息,即使它正在正确位置查找文件

"Primary script unknown" while reading response header from upstream
Run Code Online (Sandbox Code Playgroud)

验证它当前正在运行的内容:

ps aux | grep 'php-fpm'
Run Code Online (Sandbox Code Playgroud)

或更干净:

ps aux | grep -v root | grep php-fpm | cut -d\  -f1 | sort | uniq
Run Code Online (Sandbox Code Playgroud)

如何验证脚本文件名是否正确:

(在另一个答案中从 igorsantos07 窃取)

添加到httpmain 块/usr/local/etc/nginx/nginx.conf

log_format scripts '$document_root$fastcgi_script_name > $request';
Run Code Online (Sandbox Code Playgroud)

(第一位需要是您当前使用的任何内容,因此您可以查看它是否正确。)

并在您的站点server块中使用您刚刚定义的日志:

access_log /var/log/nginx/scripts.log scripts;
Run Code Online (Sandbox Code Playgroud)

如果它是正确的,请求 example.com/phpinfo.php 将产生如下内容:

/path/to/docroot/phpinfo.php > GET /phpinfo.php
Run Code Online (Sandbox Code Playgroud)

你能简化你现有的配置吗?

您是否正在使用location ~ \.php {从 Internet 某处复制/粘贴的块?大多数软件包允许您更快更干净地完成它。例如在 OS X 上,你现在只需要这个:

location ~ \.php {
    fastcgi_pass 127.0.0.1:9000;
    include snippets/fastcgi-php.conf;

    # any site specific settings, e.g. environment variables
}
Run Code Online (Sandbox Code Playgroud)

像 fastcgi_split_path_info、try_files 和 fastcgi_index(默认为 index.php)之类的东西都在/usr/local/etc/nginx/snippets/fastcgi-php.conf.

这又包括/usr/local/etc/nginx/fastcgi.confwhich 是一个fastcgi_param设置列表,包括关键的 SCRIPT_FILENAME。

不要root在 PHP 位置块中重复。

  • 非常好!是给我的!队友的欢呼声! (4认同)

We0*_*We0 8

好的,经过一天的努力,我发现了 3 件事

  1. 出于某种原因,我已经在端口 9000 上运行了一些东西,所以我更改为 9001
  2. 我的默认站点拦截了我的新站点,我再次不明白为什么,因为它不应该,但我只是取消了它的链接
  3. Nginx 不会自动为启用站点的站点提供符号链接。

希望这可以为某人节省一些麻烦!

  • 自动将符号链接从站点可用到站点启用将是不可取的。由您来制作这些符号链接,以便您可以控制服务器上哪些站点是“打开”的,哪些站点是“关闭”的。 (4认同)

Dan*_*scu 6

较新的 nginx (v1.8) 也有同样的问题。较新的版本建议使用snippets/fastcgi-php.conf;而不是fastcgi.conf. 因此,如果您include fastcgi.conf从教程中复制/粘贴,最终可能会Primary script unknown在日志中出现错误。


PLA*_*PLA 6

“主脚本未知”是由SELinux 安全上下文引起的

客户端得到响应

文件未找到。

nginx error.log 有以下错误信息

*19 FastCGI 在 stderr 中发送:从上游读取响应头时“主脚本未知”

所以只需将 Web 根文件夹的安全上下文类型更改为httpd_sys_content_t

chcon -R -t httpd_sys_content_t /var/www/show
Run Code Online (Sandbox Code Playgroud)




nginx/php-fpm 配置有 3 个用户

/etc/nginx/nginx.conf

user nobody nobody;  ### `user-1`, this is the user run nginx woker process
...
include servers/*.conf;
Run Code Online (Sandbox Code Playgroud)

/etc/nginx/conf.d/www.conf

location ~ \.php$ {
#   fastcgi_pass 127.0.0.1:9000;  # tcp socket
    fastcgi_pass unix:/var/run/php-fpm/fpm-www.sock;  # unix socket
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}
Run Code Online (Sandbox Code Playgroud)

/etc/php-fpm.d/www.conf

[www]
user = apache  ### `user-2`, this is the user run php-fpm pool process
group = apache

;listen = 127.0.0.1:9000  # tcp socket
listen = /var/run/php-fpm/fpm-www.sock  # unix socket

listen.onwer = nobody  ### `user-3`, this is the user for unix socket, like /var/run/php-fpm/fpm-www.sock
listen.group = nobody  # for tcp socket, these lines can be commented
listen.mode = 0660
Run Code Online (Sandbox Code Playgroud)

user-1 和 user-2 不必相同。

对于 unix socket,user-1 需要与 user-3 相同, 因为 nginx fastcgi_pass 必须对 unix socket 具有读/写权限。

否则 nginx 会得到502 Bad Gateway,并且 nginx error.log 有如下错误信息

*36 connect() to unix:/var/run/php-fpm/fpm-www.sock failed (13: Permission denied) 连接上游时

并且 Web 根文件夹 (/var/www/show) 的用户/组不必与这 3 个用户中的任何一个相同。