如何调试“FastCGI sent in stderr: Primary script unknown while reading response header from upstream”并找到实际的错误消息?

70

SO有许多文章提到了这个错误代码:

FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream...

那可能意味着这个错误信息基本上是毫无用处的。

这条消息告诉我们,由于某种原因,FastCGI处理程序不喜欢它接收到的内容。问题在于有时候我们不知道具体原因。

所以我再次提出问题——我们如何调试此错误代码?

考虑一下我们有一个非常简单的网站,只有phpinfo.php文件。此外,还有一个非常简单的nginx配置,如下:

server {
    server_name testsite.local;

    root /var/local/mysite/;

    location / {
        index index.html index.htm index.php;
    }

    location ~ \.php$ {
        include /etc/nginx/fastcgi_params;
        fastcgi_pass  fastcgi_backend;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

我们如何精确查看fastcgi_params发送给脚本的输出/日志?

我们如何查看实际的错误信息? 在我的情况下,我正在使用php-fpm。 它的日志中没有有关此错误的任何信息。 日志未针对此错误追加任何行。 php-fpm是否有详细模式?

/var/log/php-fpm/error.log
/var/log/php-fpm/www-error.log
我已经尝试在php-fpm.conf文件中设置此项。
log_level = notice

而这是在 php-fpm.d/www.conf 文件中的内容:

catch_workers_output = yes
10个回答

127

回答你的问题:

  1. 在 php-fpm.d/www.conf 文件中:

设置 access.log 的条目:

access.log = /var/log/$pool.access.log
  1. 重启php-fpm服务。

  2. 尝试访问您的页面

  3. 输入命令"cat /var/log/www.access.log",您将会看到如下访问日志:

- - 2016年11月10日:19:02:11 +0000 "GET /app.php" 404 - - 2016年11月10日:19:02:37 +0000 "GET /app.php" 404

解决“Primary script unknown”问题:

  • 如果您看到一行"GET /"并没有正确的php文件名,则是由于nginx配置问题引起的。

  • 如果您看到"GET /app.php"并显示404,则意味着nginx已经成功传递了脚本文件名,但php-fpm无法访问此文件(用户“php-fpm:php-fpm”无法访问您的文件,这让我困扰了3个小时)。

希望我的回答能够有所帮助。


2
我知道这是一个非常老的答案,但是对我来说,这个比其他答案更有意义。对我来说,第二点似乎是正确的,但我没有任何名为“php-fpm”的用户。我的当前用户可以访问该文件。不确定为什么现在仍然会发生这种情况。任何帮助将不胜感激。 - Shadab Faiz
5
如果您真的想看到由nginx设置的主要脚本,您应该在www.conf文件中启用“访问格式”行。 它比默认设置更详细,包含“%f”,这是真正的脚本文件。; %f:脚本文件名 ; 默认值:“%R - %u %t \“%m %r\” %s” access.format = "%R - %u %t \“%m %r%Q%q\” %s %f %{mili}d %{kilo}M %C%%" - wiktor
1
不要忘记重新启动你的php-fpm(例如:systemctl restart php7.3-fpm - Melroy van den Berg
1
有时我会间歇性地从nginx收到这个错误消息。有时我会收到primary script unknown和404,有时不会,而是会得到200。但无论哪种方式,我都得到了正确的脚本文件。 - tedders
1
在我的情况下,用户是www-data而不是php-fpm。 - cgaldiolo
显示剩余8条评论

11

当php worker处理请求时,您可以跟踪php worker以获取原因。

为了方便定位哪个worker处理请求,请在php-fpm的配置文件中仅设置一个worker。

pm.max_children = 1
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 1

使用$ps -aef | grep -v grep | grep php获取PHP的进程ID。

root     28879     1  0 Apr12 ?        00:00:02 php-fpm: master process (/etc/php-fpm.conf)
www      28880 28879  0 Apr12 ?        00:00:24 php-fpm: pool www

然后使用$ sudo strace -p 28880跟踪工作流程,然后执行请求,你将看到如下的跟踪输出。

strace: Process 28880 attached
accept(10,

{sa_family=AF_UNIX}, [112->2]) = 4
poll([{fd=4, events=POLLIN}], 1, 5000)  = 1 ([{fd=4, revents=POLLIN}])
times({tms_utime=1388, tms_stime=1099, tms_cutime=0, tms_cstime=0}) = 1336709044
read(4, "\1\1\0\1\0\10\0\0", 8)         = 8
read(4, "\0\1\0\0\0\0\0\0", 8)          = 8
read(4, "\1\4\0\1\4U\3\0", 8)           = 8
read(4, "\17DSCRIPT_FILENAME/data/HQ/SC_Edu"..., 1112) = 1112
read(4, "\1\4\0\1\0\0\0\0", 8)          = 8
lstat("/data/www/public/st/mn/dst.php", 0x7ffce98d7170) = -1 ENOENT (No such file or directory)
stat("/data/www/public/st/mn", 0x7ffce98d9580) = -1 ENOENT (No such file or directory)
stat("/data/www/public/st", 0x7ffce98d9580) = -1 ENOENT (No such file or directory)
stat("/data/www/public", {st_mode=S_IFDIR|0774, st_size=4096, ...}) = 0
...

根据跟踪输出,显示脚本文件 /data/www/public/st/mn/dst.php 不存在。


1
谢谢,这非常有用。我的错误是“资源暂时不可用”。 - Louie Miranda
1
一行代码:sudo strace -p $(pidof -S$'\n' php-fpm | tail -n1) - milahu
1
谢谢,这表明fsstat使用了AT_SYMLINK_NOFOLLOW,解释了错误的原因,因为路径中有一个符号链接。 - FuePi

4

Nginx的fastcgi_pass引起的问题不正确。

您可以检查以下内容:

打开文件:/etc/php-fpm.conf(使用systemctl status php-fpm找到它),并找到=之后的pid = 是一个路径,您需要将其与您的路径进行比较来查看是否匹配/etc/php-fpm.d/www.conf中的listen = 。 2个路径必须位于相同的位置。

例如:

pid = /run/php-fpm/php-fpm.pid

listen = /run/php-fpm/php-fpm.sock;

我的旧路径listen = /var/run/php-fpm/php-fpm.sock;我更改为/run/php-fpm/php-fpm.sock;然后重新启动php-fpm,它就能正常运行了。


你给了我清晰的思路,我的情况与你的一样,在fpm www.conf和nginx webconfig文件中,我的套接字文件路径不匹配。 - jayaprakash R

3
在我的情况下,出现了这个错误是因为php-fpm无法根据$document_root找到文件,它的值为/etc/nginx/html
通过设置:
 location ~ \.php$ {
        root /var/www/html;
        fastcgi_index   index.php;
        ...
    }

PHP-FPM现在可以正确地定位文件。


3

对我来说,这是一个权限问题,我需要在php-fpm/www.conf中更改用户和组。

将值更改为您的用户名和组 _www,例如。

user = aqib
group = _www

1

对我来说(Oracle Linux 7),是SELinux防止php-fpm访问文件。Red Hat和Centos用户可能会遇到相同的问题。

运行中

sestatus

显示SELinux的状态,对我来说它被打开导致了问题。我尝试并实施了所有其他建议的修复措施,但错误仍然存在。

我通过将SELinux置于宽容模式来解决它:

/etc/selinux/config

# cat /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=permissive
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

我的最小配置的其余部分: /etc/nginx/nginx.conf:

user  apache;
worker_processes  1;

events {
}
http {

        include mime.types;
        server {
                listen 80;
                server_name 111.222.111.222; #your ip address
                root /sites/demo;

                index index.php index.html;

                location ~ \.php$ {
                        # pass to php-fpm
                        include fastcgi.conf;
                        include fastcgi_params;
                        fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
                }

        }
}

注意:我已将用户更改为apache,这是php-fpm使用的用户。

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

 The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific IPv4 address on
;                            a specific port;
;   '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses
;                            (IPv6 and IPv4-mapped) on a specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
;listen = 127.0.0.1:9000
listen = /run/php-fpm/php-fpm.sock

; Set listen(2) backlog.
; Default Value: 511
;listen.backlog = 511

; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server.
; Default Values: user and group are set as the running user
;                 mode is set to 0660
listen.owner = apache
listen.group = apache
listen.mode = 0660

注意:我将listen.owner和listen.group设置为apache。
我的文件和文件夹权限如下: /sites(root:apache drwxrwxr-x) /sites/demo(root:apache drwxrwxr-x) /sites/demo/index.php(root:apache .rw.rw.r..)
如果你查看ps -aux | grep -E "php|nginx",你会发现所有的php-fpm池进程和nginx工作进程都是以用户apache运行的。
如果你查看套接字文件/run/php-fpm/php-fpm.sock的权限,你会发现它是由apache:apache拥有并且srw-rw----


0

检查 根目录 的位置,以及其下的文件是否存在,我遇到这个错误是因为 根路径打错了


0

对于MacOS用户,如果有人遇到了像我这样的情况:

我已经启动了php服务:

sudo brew start php72

因为我使用了“sudo”权限,所以需要停止和启动php服务而不使用sudo。

sudo brew stop php72
brew start php72

希望对某人有所帮助。


请在回答中更加具体,因为此解决方案仅适用于MAC OS而不是Linux。 - Jakki
糟糕.. 绝对正确!我刚刚添加了它。谢谢! - İsmail Atkurt

0
sudo systemctl reload php[YOUR.VERSION]-fpm

我刚刚安装了php-fpm并且没有重新启动我的Ubuntu。所以我只是运行了这个命令,问题得到解决。


-1
在我的情况下,起初我也遇到了数百万代码问题,但后来我从全局的角度看待整个大局。问题出在错误版本的PHP上。最终,我尝试逐个更换不同版本的PHP,就像这样:
fastcgi_pass unix:/run/php/php7.3-fpm.sock

fastcgi_pass unix:/run/php/php5.3-fpm.sock

然后它就可以工作了,而不必重新开发和更改数百万行代码。我知道这有点傻,但如果以旧的方式和旧的PHP方法开发,新的PHP版本绝对会崩溃一切。对我来说,让它工作比运行最新的PHP版本更重要。


1
这很大程度上是试错过程,而实际上应该是已知的,即您的上游套接字路径。在php-fpm配置中,listen指令设置了该值,如果有疑问,请检查运行目录以获取实际套接字名称... - OldFart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接