我注意到 PHP-FPM 存在以下行为:
看一下这两个 Nginx 配置:
server {
listen 80;
server_name example.com;
location / {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /srv/www/i.php;
fastcgi_param PHP_VALUE "display_errors=1";
include fastcgi_params;
}
}
server {
listen 80;
server_name example.net;
location / {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /srv/www/i.php;
include fastcgi_params;
}
}
和/srv/www/i.php
文件:
<?php phpinfo();
正如您所见,唯一的区别是fastcgi_param PHP_VALUE "display_errors=1";
。
现在,如果你杀死所有 FPM 工作者,然后example.net
首先打开,你会看到 ,display_errors
正如预期的那样Off
。 并且example.com
你将看到。display_errors
On
但如果你example.net
再次访问和该请求由同一工作人员处理,您将display_errors
获得On
。
所有 FPM 工作者都在同一个池中工作。
问题:如何使example.net
始终使用默认设置?
可能的解决方案:
- 在配置中也定义
PHP_VALUE
所需的设置。example.net
- 似乎是一个“正确”的解决方案——为每个站点创建单独的工人池。
但是我们的服务器上有很多网站,这两种解决方案都意味着需要进行大量日常设置工作。我想知道是否有更简单的方法。
更新:
display_errors
我示例中的设置只是为了演示问题。任何php.ini
设置都会发生同样的情况。正如评论所说,在一台服务器上混合生产和开发站点是个坏主意。
答案1
发生这种情况的原因很可能是“使用 php_value 或 php_flag 传递的 PHP 设置将覆盖其先前的值”,如下所述PHP-FPM 文档。
我假设您的 PHP 配置display_errors
已禁用。然后您访问 .net 页面,确认phpinfo()
它已被禁用。
然后您访问 .com 页面,Nginx 会将 传递display_errors=1
给同一池中的 PHP-FPM 工作器。这会0
用新值覆盖 的先前值1
。您可以使用 进行确认phpinfo()
。
现在 PHP-FPM 池设置已设为display_errors=1
。
当您再次访问 .net 页面时,phpinfo()
确实可以确认,display_errors=1
因为当 Nginx 将值传递1
给现在处理您的另一个网站的同一池时,它被覆盖了。
解决方案要么是将开发转移到另一台服务器,如评论中所建议的那样。要么是为您的网站创建一个专用的 PHP-FPM 池,这是您应该做的最少的事情。
奖金:
请不要在您的 Nginx 配置中执行以下操作:fastcgi_param PHP_VALUE "display_errors=1";
这应该在 php 配置文件中,最好是在站点自己的 fpm 池配置中。
但是我们的服务器上有很多网站,这两种解决方案都意味着需要进行大量日常设置工作。我想知道是否有更简单的方法。
您可以使用 per pool 前缀来快速修复。无论如何,将多个网站放在一个工作池上不是一个好主意,因为我只需要让其中一个网站执行我的恶意 php 脚本,就可以毫不费力地入侵使用相同工作池的所有其他网站。