如何调试 "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?
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;
}
}
我们如何才能准确地看到 output/log 向脚本发送了什么 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
回答你的问题:
- 在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
要解决 "Primary script unknown" 问题:
如果您看到 "GET /" 没有正确的 php 文件名,那么这是您的 nginx conf 问题。
如果你看到 "GET /app.php" 和 404,这意味着 nginx 正确地传递了脚本文件名但是 php-fpm 无法访问这个文件(用户 "php-fpm:php-fpm" 无法访问您的文件,这让我困了 3 个小时)
希望我的回答对您有所帮助。
MacOs用户,以防有人遇到像我这样的情况:
我已经开始 php 服务:
sudo brew start php72
因为我使用了 "sudo" 权限不同。我需要在没有 sudo 的情况下停止和启动 php 服务。
sudo brew stop php72
brew start php72
希望对某人有所帮助。
检查 root 的位置以及它下面的文件是否存在,我遇到这个错误是因为 Root path TYPO 。
对我来说这是一个权限问题,我不得不在 php-fpm/www.conf
中更改用户和组
将值更改为您的用户名和组 _www,例如
user = aqib
group = _www
由于请求是由 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, "[=12=][=12=][=12=][=12=]", 8) = 8
read(4, "[=12=][=12=][=12=][=12=][=12=][=12=][=12=]", 8) = 8
read(4, "[=12=]U[=12=]", 8) = 8
read(4, "DSCRIPT_FILENAME/data/HQ/SC_Edu"..., 1112) = 1112
read(4, "[=12=][=12=][=12=][=12=][=12=]", 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
未退出
对我来说 (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 池进程和 nginx 工作进程都是 运行 作为用户 apache.
如果您查看套接字文件 /run/php-fpm/php-fpm.sock 的权限,您会看到它属于 apache:apache 和 srw-rw----
Nginx的问题fastcgi_pass不对
您可以检查以下内容:
打开文件:/etc/php-fpm.conf
(systemctl 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 然后它 运行 很好。
在我的例子中,出现这个错误是因为 php-fpm 无法根据 $document_root
找到文件,即 /etc/nginx/html
通过设置
location ~ \.php$ {
root /var/www/html;
fastcgi_index index.php;
...
}
PHP-FPM 现在可以正确定位文件。
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;
}
}
我们如何才能准确地看到 output/log 向脚本发送了什么 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
回答你的问题:
- 在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
要解决 "Primary script unknown" 问题:
如果您看到 "GET /" 没有正确的 php 文件名,那么这是您的 nginx conf 问题。
如果你看到 "GET /app.php" 和 404,这意味着 nginx 正确地传递了脚本文件名但是 php-fpm 无法访问这个文件(用户 "php-fpm:php-fpm" 无法访问您的文件,这让我困了 3 个小时)
希望我的回答对您有所帮助。
MacOs用户,以防有人遇到像我这样的情况:
我已经开始 php 服务:
sudo brew start php72
因为我使用了 "sudo" 权限不同。我需要在没有 sudo 的情况下停止和启动 php 服务。
sudo brew stop php72
brew start php72
希望对某人有所帮助。
检查 root 的位置以及它下面的文件是否存在,我遇到这个错误是因为 Root path TYPO 。
对我来说这是一个权限问题,我不得不在 php-fpm/www.conf
将值更改为您的用户名和组 _www,例如
user = aqib
group = _www
由于请求是由 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
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, "[=12=][=12=][=12=][=12=]", 8) = 8
read(4, "[=12=][=12=][=12=][=12=][=12=][=12=][=12=]", 8) = 8
read(4, "[=12=]U[=12=]", 8) = 8
read(4, "DSCRIPT_FILENAME/data/HQ/SC_Edu"..., 1112) = 1112
read(4, "[=12=][=12=][=12=][=12=][=12=]", 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
未退出
对我来说 (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 池进程和 nginx 工作进程都是 运行 作为用户 apache.
如果您查看套接字文件 /run/php-fpm/php-fpm.sock 的权限,您会看到它属于 apache:apache 和 srw-rw----
Nginx的问题fastcgi_pass不对
您可以检查以下内容:
打开文件:/etc/php-fpm.conf
(systemctl 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 然后它 运行 很好。
在我的例子中,出现这个错误是因为 php-fpm 无法根据 $document_root
找到文件,即 /etc/nginx/html
通过设置
location ~ \.php$ {
root /var/www/html;
fastcgi_index index.php;
...
}
PHP-FPM 现在可以正确定位文件。