为什么同一台服务器上的两个网站会(随机)使用 PHP-FPM 切换 PHP 版本

为什么同一台服务器上的两个网站会(随机)使用 PHP-FPM 切换 PHP 版本

我的问题如下:

1 台在虚拟机中运行 Debian 11 的服务器(尽管我已经测试过 9 和 10,它们都显示相同的行为)

有 2 个网站都配置为使用 php-fpm 和 apache 运行。每个网站都有一个 index.php 文件,这些文件的内容是<?php phpinfo(); ?>。1 个网站已设置为运行 php8.0,另一个网站运行 php8.1,这代表我正在处理的真实情况。这是通过将 apache 配置文件包含到每个网站的主 apache 配置文件中来完成设置的,内容如下:

<IfModule proxy_fcgi_module>
# Enable http authorization headers
<IfModule setenvif_module>
SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
</IfModule>

<FilesMatch ".+\.ph(ar|p|tml)$">
    <If "-f %{REQUEST_FILENAME}">
        SetHandler "proxy:unix:/run/php/php8.0-fpm.sock|fcgi://localhost"
    </If>
</FilesMatch>
<FilesMatch ".+\.(phps|inc)$">
    # Deny access to raw php sources by default
    # To re-enable it's recommended to enable access to the files
    # only in specific virtual host or directory
    Require all denied
</FilesMatch>
# Deny access to files without filename (e.g. '.php')
<FilesMatch "^\.ph(ar|p|ps|tml)$">
    Require all denied
</FilesMatch>

然后,php8.1 的配置文件使用 php8.1-fpm.sock。ps aux 显示以下内容:

root      114787  0.0  0.3 222780 27312 ?        Ss   17:10   0:00 php-fpm: master process (/etc/php/8.0/fpm/php-fpm.conf)
www-data  114788  0.0  0.5 247140 48664 ?        S    17:10   0:03 php-fpm: pool www
www-data  114789  0.0  0.5 247128 48592 ?        S    17:10   0:03 php-fpm: pool www
www-data  114790  0.0  0.6 247136 48748 ?        S    17:10   0:03 php-fpm: pool www
www-data  114791  0.0  0.5 247128 48676 ?        S    17:10   0:05 php-fpm: pool www
www-data  114792  0.0  0.5 247132 48548 ?        S    17:10   0:04 php-fpm: pool www
root      114802  0.0  0.3 227196 28120 ?        Ss   17:10   0:00 php-fpm: master process (/etc/php/8.1/fpm/php-fpm.conf)
www-data  114803  0.0  0.3 227764 26744 ?        S    17:10   0:00 php-fpm: pool www
www-data  114804  0.0  0.1 227196  8896 ?        S    17:10   0:00 php-fpm: pool www
www-data  114805  0.0  0.1 227196  8896 ?        S    17:10   0:00 php-fpm: pool www
www-data  114806  0.0  0.1 227196  8896 ?        S    17:10   0:00 php-fpm: pool www

/etc/php/8.0/fpm/pool.d/www.conf 的内容:

[www]

user = www-data
group = www-data

listen = /run/php/php8.0-fpm.sock

listen.owner = www-data
listen.group = www-data

pm = dynamic

pm.max_children = 5

pm.start_servers = 2

pm.min_spare_servers = 1

pm.max_spare_servers = 3

/etc/php/8.1/fpm/pool.d/www.conf 的内容完全相同,只是 listen = /run/php/php8.1-fpm.sock

/etc/php80/apache-include.conf 的内容(对于 php8.1,请用 81 替换):

Alias   /php80 /etc/php80/htdocs
<Directory /etc/php80/htdocs>
    <IfModule proxy_fcgi_module>
        Include /etc/php80/etc/php-apache2-fpm.conf
    </IfModule>
</Directory>
<Location  /php80 >
    Options FollowSymLinks
    <IfModule mod_php7.c>
        Include /etc/php80/etc/php-apache2.conf
    </IfModule>
        SetEnv  st_config_filepath /etc/php80/config.ini
    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteOptions inherit
        # Maintenance for this installation
        RewriteCond /etc/php80/maintenance -f
        RewriteCond %{HTTP_USER_AGENT} !Maintenance_Override
        RewriteRule ^.*$ /maintenance/?  [L,R=307]
    </IfModule>
</Location>    
# Deny access to simplesaml directories    
<DirectoryMatch "^/etc/php80/htdocs/libraries/simplesamlphp/(?!(auth|resources|module.php)).+">
        Order deny,allow
        Deny from all
</DirectoryMatch>

/etc/apache2/sites-enabled/ssl.conf 的内容

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerAdmin webmaster@*.*    
    ServerName ${APACHE_LOCALFQDN}
    ServerAlias ${APACHE_HOSTNAME}    
    DocumentRoot /var/www/html/    
    <Directory />
        Options
        AllowOverride None
    </Directory>    
    <Directory /var/www/html/>
        Options FollowSymLinks
        AllowOverride None
        Order allow,deny
        allow from all
    </Directory> 
# Logging

# For proxied requests, log different information:
    SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded

# Proxied access log:
    LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" proxy
    CustomLog ${APACHE_LOG_DIR}/${APACHE_LOCALFQDN}-ssl.access-proxy.log proxy env=forwarded
 
# SSL Configuration
SSLEngine on
SSLOptions StdEnvVars OptRenegotiate
SSLCertificateFile /etc/ssl/private/${APACHE_LOCALFQDN}.crt
SSLCertificateKeyFile /etc/ssl/private/${APACHE_LOCALFQDN}.key

<FilesMatch "\.(php)$">
    SSLOptions +StdEnvVars
</FilesMatch>
BrowserMatch "MSIE [2-6]" \
    nokeepalive ssl-unclean-shutdown \
    downgrade-1.0 force-response-1.0    
BrowserMatch "MSIE [7-9]" ssl-unclean-shutdown

################################################################################
# SSL hardening options
#Probably not relevant to show here

</VirtualHost>
</IfModule>

我在 php80/ 和 php81 目录中有一个 php.sh 文件:

#!/bin/sh -e
. /etc/php80/etc/php-cli.sh

env config_filepath=/etc/php80/config.ini /usr/bin/${PHPVERSION:=php7.3} ${PHPOPTIONS} $*

php-cli.sh的内容为:

PHPOPTIONS="-d magic_quotes_gpc=off -d register_globals=off -d safe_mode=off -d session.use_trans_sid=off -d output_buffering=off -d zlib.output_compression=off -d ignore_user_abort=on -d upload_max_filesize=1500M -d post_max_size=1500M -d memory_limit=-1 -d date.timezone=Europe/Berlin"

PHPVERSION="${FORCE_PHP_VERSION:-php8.0}"

php81 随后已正确设置相关部分。

我真正不明白的以及我的问题所在是,为什么当我不断刷新各个页面时,我有时会看到 8.0 网站显示它正在使用 php8.1,反之亦然。我有时必须刷新页面 10-20 次才能切换,但它总是会很快出现。

我该如何弄清楚为什么会发生这种情况,或者我是否忽略了一些非常明显的事情?

提前谢谢了!

进一步研究/可能的解释:

1.php fpm 主进程均以 root 身份运行,所有子进程均以 www-data 身份运行(如上 ps aux 输出所示)。https://www.binarytides.com/php-fpm-separate-user-uid-linux/这表明尽管使用不同的套接字,但实际上任何池都可以用于请求,因为它们都在 www-data 用户下运行:

“使用自己的 uid/gid 运行每个站点更安全,也更容易处理。如果所有站点都使用同一个用户运行,那么一个站点上的 php 就可以读取/写入其他用户的文件。”

1.1. 经过进一步的实验,我发现更改 php8.0 或 8.1 的池名称不足以将其与任何主进程分离,在我看来,这使之前引用的文章具有可信度,该文章指出还需要设置不同的用户/组。ps aux | grep php 的屏幕截图

1.1.1.好吧,最后一项就不提了,我之前没有意识到 ps aux 没有显示进程之间的关系。ps afx 显示子进程分配正确。不幸的是,我以为我已经找到了,但实际上并没有。

 161186 ?        Ss     0:01 php-fpm: master process (/etc/php/8.0/fpm/php-fpm.conf)
 161191 ?        S      0:10  \_ php-fpm: pool php80
 161192 ?        S      0:11  \_ php-fpm: pool php80
 161193 ?        S      0:07  \_ php-fpm: pool php80
 161205 ?        Ss     0:01 php-fpm: master process (/etc/php/8.1/fpm/php-fpm.conf)
 161206 ?        S      0:00  \_ php-fpm: pool www
 161207 ?        S      0:00  \_ php-fpm: pool www

我现在已经测试设置不同的用户和组,但仍然看到相同的行为

2.看来这个问题实际上之前遇到过

尝试了 phpinfo() 页面,得到的是 PHP 7.4.15,而不是预期的 5.6.40。我们对 7.3 做了同样的操作,同样使用 php7.3 的 SetHandler 在 phpinfo() 上得到了相同的 7.4。

我已经测试了所提出的解决方案(放弃 Linux 套接字并改用网络通信),并确认它有效。不幸的是,这不是一个理想的解决方案,并且无法解释为什么使用套接字无法正常工作。涉及的解决方案<If "-f %{REQUEST_FILENAME}">我已经存在,但没有任何效果。

3.我发现我们设置的另外 2 个系统使用 Debian 10.12 和 Apache 2.4.54(而不是上例中的 Apache 2.4.53),以及 Debian 11.4 和 Apache 2.4.54。对于这些系统,我们使用 .htaccess 文件,而不是每个站点使用单独的 Apache 配置,在这些条件下,该问题无法重现

相关内容