|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2010-12-26 00:37 UTC] jraxis at gmail dot com
Description:
------------
In nginx+FPM, if I set a PHP_VALUE using fastcgi_param in one server, sometimes other virtual hosts are seeing those settings. An nginx.conf fragment like this:---
server {
server_name foo.example;
root /srv/www/foo.example;
...
location ~ \.php$ {
... # usual PHP stuff
}
}
server {
server_name bar.example;
root /srv/www/bar.example;
...
location ~ \.php$ {
...
fastcgi_param PHP_VALUE "auto_prepend_file=\"/etc/nginx/bar.php\""
}
}
---will occasionally result in foo.example's pages having bar.php prepended to it. The php-fpm processes are most likely retaining the PHP_VALUE settings as they are re-used by nginx for requests for other virtual hosts.
This is with PHP/5.3.4 and nginx/0.8.53 on a Gentoo Linux box. ./configure line:---
'./configure' '--prefix=/usr' '--build=i686-pc-linux-gnu' '--host=i686-pc-linux-gnu' '--mandir=/usr/share/man' '--infodir=/usr/share/info' '--datadir=/usr/share' '--sysconfdir=/etc' '--localstatedir=/var/lib' '--prefix=/usr/lib/php5.3' '--mandir=/usr/lib/php5.3/man' '--infodir=/usr/lib/php5.3/info' '--libdir=/usr/lib/php5.3/lib' '--with-libdir=lib' '--without-pear' '--disable-maintainer-zts' '--enable-bcmath=shared' '--with-bz2=shared' '--enable-calendar=shared' '--with-curl=shared' '--with-curlwrappers' '--without-enchant' '--enable-exif=shared' '--enable-ftp=shared' '--with-gettext=shared' '--with-gmp=shared' '--disable-intl' '--without-kerberos' '--enable-mbstring=shared' '--with-mcrypt=shared' '--without-mssql' '--with-onig=/usr' '--with-openssl' '--with-openssl-dir=/usr' '--enable-pcntl=shared' '--without-pgsql' '--without-pspell' '--without-recode' '--enable-shmop' '--with-snmp=shared' '--enable-soap=shared' '--enable-sockets=shared' '--without-sybase-ct' '--enable-sysvmsg=shared' '--enable-sysvsem=shared' '--enable-sysvshm=shared' '--with-tidy=shared' '--enable-wddx=shared' '--with-xmlrpc=shared' '--with-xsl=shared' '--enable-zip=shared' '--with-zlib=shared' '--disable-debug' '--enable-dba=shared' '--without-cdb' '--with-db4' '--enable-flatfile' '--with-gdbm' '--enable-inifile' '--without-qdbm' '--with-freetype-dir=/usr' '--with-t1lib=/usr' '--enable-gd-jis-conv' '--with-jpeg-dir=/usr' '--with-png-dir=/usr' '--with-xpm-dir=/usr' '--with-gd' '--with-imap=shared' '--with-imap-ssl' '--without-interbase' '--with-ldap=shared' '--with-ldap-sasl' '--with-mysql=shared,/usr' '--with-mysql-sock=/var/run/mysqld/mysqld.sock' '--with-mysqli=shared,/usr/bin/mysql_config' '--with-unixODBC=shared,/usr' '--without-adabas' '--without-birdstep' '--without-dbmaker' '--without-empress' '--without-esoob' '--without-ibm-db2' '--without-sapdb' '--without-solid' '--without-oci8' '--without-pdo-dblib' '--with-pdo-mysql=shared,/usr' '--without-pdo-pgsql' '--with-pdo-sqlite=shared,/usr' '--with-pdo-odbc=shared,unixODBC,/usr' '--with-readline' '--without-libedit' '--with-mm' '--with-sqlite=/usr' '--enable-sqlite-utf8' '--with-pcre-regex=/usr' '--with-pcre-dir=/usr' '--with-config-file-path=/etc/php/fpm-php5.3' '--with-config-file-scan-dir=/etc/php/fpm-php5.3/ext-active' '--disable-cli' '--disable-cgi' '--enable-fpm' '--disable-embed' '--without-apxs2'
Test script:
---------------
# /srv/www/foo.example/index.php
<?php print "Foo index"; ?>
# /srv/www/bar.example/index.php
<?php print "Bar index"; ?>
# /etc/nginx/bar.php
<?php print "Bar prepend<br/>"; ?>
Expected result:
----------------
# foo.example
Foo index
# bar.example
Bar prepend
Bar index
Actual result:
--------------
# foo.example
Bar prepend
Foo index
# bar.example
Bar prepend
Bar index
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Nov 02 00:00:01 2025 UTC |
Hi, I can confirm the bug, I have the same issue. I have Nginx with php5-fpm as multi vhost (using sites-enabled & sites-available structure) for one of my sites I have: location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi_params; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PHP_VALUE "include_path=/path/to/includes"; fastcgi_pass 127.0.0.1:9000; } Now my other vhost website (other url) with the same conf setup but minus the fastcgi_param PHP_VALUE "include_path=/path/to/includes"; line is searching for includes at the exact same place instead of locally. I'm running Debian 6, nginx + php5-fpm + xcache (+ memcache + memcached). What files do you need for further investigation? fpm conf: ;;;;;;;;;;;;;;;;;;;;; ; FPM Configuration ; ;;;;;;;;;;;;;;;;;;;;; ; All relative paths in this configuration file are relative to PHP's install ; prefix (/usr). This prefix can be dynamicaly changed by using the ; '-p' argument from the command line. ; Include one or more files. If glob(3) exists, it is used to include a bunch of ; files from a glob(3) pattern. This directive can be used everywhere in the ; file. ; Relative path can also be used. They will be prefixed by: ; - the global prefix if it's been set (-p arguement) ; - /usr otherwise ;include=/etc/php5/fpm/*.conf ;;;;;;;;;;;;;;;;;; ; Global Options ; ;;;;;;;;;;;;;;;;;; [global] ; Pid file ; Note: the default prefix is /var ; Default Value: none pid = /var/run/php5-fpm.pid ; Error log file ; If it's set to "syslog", log is sent to syslogd instead of being written ; in a local file. ; Note: the default prefix is /var ; Default Value: log/php-fpm.log error_log = /var/log/php5-fpm.log ; syslog_facility is used to specify what type of program is logging the ; message. This lets syslogd specify that messages from different facilities ; will be handled differently. ; See syslog(3) for possible values (ex daemon equiv LOG_DAEMON) ; Default Value: daemon ;syslog.facility = daemon ; syslog_ident is prepended to every message. If you have multiple FPM ; instances running on the same server, you can change the default value ; which must suit common needs. ; Default Value: php-fpm ;syslog.ident = php-fpm ; Log level ; Possible Values: alert, error, warning, notice, debug ; Default Value: notice ;log_level = notice ; If this number of child processes exit with SIGSEGV or SIGBUS within the time ; interval set by emergency_restart_interval then FPM will restart. A value ; of '0' means 'Off'. ; Default Value: 0 emergency_restart_threshold = 10 ; Interval of time used by emergency_restart_interval to determine when ; a graceful restart will be initiated. This can be useful to work around ; accidental corruptions in an accelerator's shared memory. ; Available Units: s(econds), m(inutes), h(ours), or d(ays) ; Default Unit: seconds ; Default Value: 0 emergency_restart_interval = 1m ; Time limit for child processes to wait for a reaction on signals from master. ; Available units: s(econds), m(inutes), h(ours), or d(ays) ; Default Unit: seconds ; Default Value: 0 process_control_timeout = 10s ; The maximum number of processes FPM will fork. This has been design to control ; the global number of processes when using dynamic PM within a lot of pools. ; Use it with caution. ; Note: A value of 0 indicates no limit ; Default Value: 0 ; process.max = 128 ; Specify the nice(2) priority to apply to the master process (only if set) ; The value can vary from -19 (highest priority) to 20 (lower priority) ; Note: - It will only work if the FPM master process is launched as root ; - The pool process will inherit the master process priority ; unless it specified otherwise ; Default Value: no set ; process.priority = -19 ; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging. ; Default Value: yes ;daemonize = yes ; Set open file descriptor rlimit for the master process. ; Default Value: system defined value ;rlimit_files = 1024 ; Set max core size rlimit for the master process. ; Possible Values: 'unlimited' or an integer greater or equal to 0 ; Default Value: system defined value ;rlimit_core = 0 ; Specify the event mechanism FPM will use. The following is available: ; - select (any POSIX os) ; - poll (any POSIX os) ; - epoll (linux >= 2.5.44) ; - kqueue (FreeBSD >= 4.1, OpenBSD >= 2.9, NetBSD >= 2.0) ; - /dev/poll (Solaris >= 7) ; - port (Solaris >= 10) ; Default Value: not set (auto detection) ; events.mechanism = epoll ;;;;;;;;;;;;;;;;;;;; ; Pool Definitions ; ;;;;;;;;;;;;;;;;;;;; ; Multiple pools of child processes may be started with different listening ; ports and different management options. The name of the pool will be ; used in logs and stats. There is no limitation on the number of pools which ; FPM can handle. Your system will tell you anyway :) ; To configure the pools it is recommended to have one .conf file per ; pool in the following directory: include=/etc/php5/fpm/pool.d/*.confDuring migration from mod_php to FPM we stumbled across this too. So I've written a small patch which uses Zend INI to restore the altered INI settings after each request: diff -Naur php-5.5.16.orig/sapi/fpm/fpm/fpm_main.c php-5.5.16/sapi/fpm/fpm/fpm_main.c --- php-5.5.16.orig/sapi/fpm/fpm/fpm_main.c 2014-08-21 10:45:02.000000000 +0200 +++ php-5.5.16/sapi/fpm/fpm/fpm_main.c 2014-09-15 16:05:27.777482784 +0200 @@ -1405,7 +1405,6 @@ int *mode = (int *)arg; char *key; char *value = NULL; - struct key_value_s kv; if (!mode || !arg1) return; @@ -1416,7 +1415,7 @@ key = Z_STRVAL_P(arg1); - if (!key || strlen(key) < 1) { + if (!key || Z_STRLEN_P(arg1) < 1) { zlog(ZLOG_ERROR, "Passing INI directive through FastCGI: empty key"); return; } @@ -1430,10 +1429,7 @@ return; } - kv.key = key; - kv.value = value; - kv.next = NULL; - if (fpm_php_apply_defines_ex(&kv, *mode) == -1) { + if (zend_alter_ini_entry(key, Z_STRLEN_P(arg1) + 1, value, Z_STRLEN_P(arg2), *mode, PHP_INI_STAGE_HTACCESS) == FAILURE) { zlog(ZLOG_ERROR, "Passing INI directive through FastCGI: unable to set '%s'", key); } }I have had the same experience using PHP 5.6.18 on CentOS 7.2.1511 as described. I got around the issue by giving each server {} it's own php-fpm.d pool in the line fastcgi_pass unix:/var/run/php-fpm/website.sock; This seemed to eliminate the cross talk. Now I have installed the SquirrelMail php webmail system and I get cross talk between the location /squirrelmail {...} block and location ~ \.php$ {...} block When handling a request for a location under /squirrelmail, it would give a file not found error for the "auto_prepend_file=..file.." from the location ~ \.php$ {...} block. I found a workaround as shown below by adding fastcgi_param PHP_VALUE "auto_prepend_file="; to the /squirrelmail block. Maybe there's a better standard way of getting each location's PHP_VALUE setting handled correctly. server { listen 80; server_name website.com; root /var/www/website.com/html; index index.php; location / { try_files $uri $uri/ =404; } location /squirrelmail { root /usr/share/; index index.php index.html index.htm; location ~ ^/squirrelmail/(.+\.php)$ { try_files $uri =404; root /usr/share/; fastcgi_pass unix:/var/run/php-fpm/website.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PHP_VALUE "auto_prepend_file="; include /etc/nginx/fastcgi_params; } location ~* ^/squirrelmail/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ { root /usr/share/; } } location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php-fpm/website.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PHP_VALUE "auto_prepend_file=/var/www/website.com/core/lib.common.php"; include fastcgi_params; } }I can confirm this issue is still valid for php 7.0.12 and 7.1.3. Excerpt from nginx.conf: location ~ \.php$ { root /var/www/html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~ _pre\.php$ { root /var/www/html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PHP_VALUE "auto_prepend_file=/var/www/html/die.php"; include fastcgi_params; } # cat /var/www/html/index.php <?php die("index\n"); # cat /var/www/html/die.php <?php die("foo\n"); and index_pre.php is just a symlink to index.php: # curl http://localhost/index.php index # curl http://localhost/index_pre.php foo # curl http://localhost/index.php foo