如何调试“FastCGI sent in stderr: Primary script unknown while reading response header from upstream”并找到实

Posted

技术标签:

【中文标题】如何调试“FastCGI sent in stderr: Primary script unknown while reading response header from upstream”并找到实际的错误消息?【英文标题】:How to debug "FastCGI sent in stderr: Primary script unknown while reading response header from upstream" and find the actual error message? 【发布时间】:2016-05-17 15:50:10 【问题描述】:

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

【问题讨论】:

【参考方案1】:

回答您的问题:

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

设置 access.log 条目:

access.log = /var/log/$pool.access.log

    重启php-fpm服务。

    尝试访问您的页面

    cat /var/log/www.access.log,你会看到如下访问日志:

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

解决“主脚本未知”问题:

如果您看到“GET /”没有正确的 php 文件名,那么这是您的 nginx 配置问题。

1234563 '无权访问你的文件,这让我困了 3 个小时)

希望我的回答有帮助。

【讨论】:

我知道这是一个很老的答案,但这个答案对我来说比另一个答案更有意义。对我来说,第 2 点似乎是这样,但我没有任何用户“php-fpm”。我当前的用户有权访问该文件。不知道为什么它现在会发生。任何帮助将不胜感激。 如果你真的想看到 nginx 设置的主脚本,你应该在 www.conf 文件中启用access format 行。它比默认的更详细,包含%f,这是真正的脚本文件。 ; %f: script filename ; Default: "%R - %u %t \"%m %r\" %s" access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %milid %kiloM %C%%" 别忘了重启你的php-fpm(例如systemctl restart php7.3-fpm 我间歇性地从 nginx 收到此错误消息。有时我会得到未知的主脚本和 404,有时我没有得到 200。无论哪种方式,我都会得到正确的脚本文件 在我的例子中,用户是 www-data 而不是 php-fpm【参考方案2】:

对我来说这是一个权限问题,我不得不更改 php-fpm/www.conf 中的用户和组

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

user = aqib
group = _www

【讨论】:

【参考方案3】:

Nginx 的 fastcgi_pass 不正确导致的问题。

您可以检查以下内容:

打开文件:/etc/php-fpm.confsystemctl status php-fpm 找到它)并在 = 之后找到 pid = 是您需要与您的路径进行比较的路径 listen = 在文件/etc/php-fpm.d/www.conf 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 然后它运行良好。

【讨论】:

【参考方案4】:

由于请求是由 php worker 处理的,所以可以通过 php worker 追踪到原因。

为了方便定位哪个worker处理请求,在php-fpm的conf文件中只设置一个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工作pid

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 未退出

【讨论】:

【参考方案5】:

在我的情况下,发生此错误是因为 php-fpm 无法根据$document_root 找到文件,即/etc/nginx/html

通过设置

 location ~ \.php$ 
        root /var/www/html;
        fastcgi_index   index.php;
        ...
    

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

【讨论】:

【参考方案6】:

检查root的位置以及它下面的文件是否存在,我遇到了这个错误,因为Root path TYPO

【讨论】:

【参考方案7】:

对我(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

我的文件和文件夹的权限是: /站点(根: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 pool进程和nginx worker进程都以用户apache运行。

如果您查看套接字文件 /run/php-fpm/php-fpm.sock 的权限,您将看到它由 apache:apache 和 srw-rw 拥有----

【讨论】:

【参考方案8】:

对于MacOs用户,如果有人遇到我这种情况:

我已经启动了 php 服务:

sudo brew start php72

因为我使用了“sudo”权限是不同的。我需要在没有 sudo 的情况下停止和启动 php 服务。

sudo brew stop php72
brew start php72

希望对某人有所帮助。

【讨论】:

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

以上是关于如何调试“FastCGI sent in stderr: Primary script unknown while reading response header from upstream”并找到实的主要内容,如果未能解决你的问题,请参考以下文章

如何在PyCharm中调试程序

如何使用VC进行远程调试

如何使用真机调试android程序

如何在 iPhone Safari 上调试网页

如何使用ADB进行调试

如何使用真机调试android程序