最後更新: 2018-01-22
目錄
介紹
php5-fpm - PHP FastCGI Process Manager
* process spawning
systemd-+... |-php-fpm-+-php-fpm | |-php-fpm | |-php-fpm | |-php-fpm | |-php-fpm | `-php-fpm
Pool
不同的 Pool 是不同設定的 php process, 比如 php version, upload_max_filesize
Pool 是用不同的 port 去區分 (Default first pool: 9000/TCP)
Daemon
runs as a daemon and receives Fast/CGI requests.
Browser --> Nginx --> php-fpm --> php
* 當 Nginx 連不到 php-fpm proccess 時, 那 client 會收到 "502 Bad Gateway"
php5-fpm
Opts:
- -t Test FPM configuration file
- -i PHP information and configuration
- -m Show compiled in modules
php*-fpm 設定
php-fpm 主設定檔
/etc/php5/fpm/php-fpm.conf
; The maximum number of processes FPM will fork. ; The global number of processes when using dynamic PM within a lot of pools. process.max = 64 ; child processes to wait for a reaction on signals from master process_control_timeout = 0 ; Set open file descriptor rlimit for the master process rlimit_files = 10240 ; -19 (highest priority) to 20 (lower priority) process.priority = 1 # 每個 Pool 的獨立 Setting include=/etc/php5/fpm/pool.d/*.conf
Pool 的設定
/etc/php5/fpm/pool.d/www.conf
# 這是 pool 的名, variable $pool 相當於這字 [www] # 這 pool 的 proccess 的執行身分 user = www-data group = www-data # TCP listen = 127.0.0.1:9000 listen.allowed_clients = 127.0.0.1 # backlog: maximum length to which the queue of pending connections # man 2 listen 有解釋. Default: -1 => unlimited. 另見 listen.backlog = 128 # Socket listen = /var/run/php5-fpm.sock listen.owner = www-data listen.group = www-data listen.mode = 0660 # Proccess 數量設定 pm = dynamic # alive at the same time (ApacheMaxClients) # simultaneous requests that will be served. pm.max_children = 32 # children created on startu pm.start_servers = 4 # children in 'idle' pm.min_spare_servers = 2 pm.max_spare_servers = 6 # idle process will be killed pm.process_idle_timeout = 10s # each child process should execute before respawning pm.max_requests = 1024 # real-time FPM status monitoring # Default Value: not set # http://127.0.0.1/status Or http://www.foo.bar/status?full pm.status_path = /status # The access log file ; Default: not set ; Default Format: "%R - %u %t \"%m %r\" %s" ; %R: remote IP address ; %u: remote user ; %t: server time ; %m: request method ; %r: the request URI ; %s: status access.log = /var/log/fpm-php/pool/$pool.access.log ; The log file for slow requests slowlog = /var/log/fpm-php/pool/$pool.log.slow request_slowlog_timeout = 10 request_terminate_timeout = 10m # Limits the extensions of the main script FPM will allow to parse. security.limit_extensions = .php .php3 .php4 .php5 # Additional php.ini defines, specific to this pool of workers. php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f [email protected] php_flag[display_errors] = off php_admin_value[error_log] = /var/log/fpm-php/pool/$pool.log php_admin_flag[log_errors] = on php_admin_value[memory_limit] = 128M php_admin_value[max_execution_time] = 180 php_admin_value[date.timezone] = Asia/Hong_Kong php_admin_value[upload_max_filesize] = 15M php_admin_value[post_max_size] = 20M php_admin_value[short_open_tag] = on
# Restart Service
service php-fpm restart
nginx 與 php 的溝通時間
nginx
fastcgi_connect_timeout 300s; fastcgi_send_timeout 300s; fastcgi_read_timeout 300s;
php-fpm
php_admin_value[max_execution_time] = 300 php_admin_value[max_input_time] = 300 php_admin_value[default_socket_timeout] = 300
Data size
client_max_body_size 50M;
FPM Log
Default: /var/log/php-fpm.log
Setting: /etc/php-fpm.conf
; If it's set to "syslog", log is sent to syslogd instead of file error_log = /var/log/php-fpm/error.log log_level = notice
Or
;syslog.facility = daemon ;syslog.ident = php-fpm
Nginx FPM 設定
snippets/php56-fpm.conf
location ~* \.php$ {
# The "if" lets NGINX check whether the *.php does indeed exist
# to prevent NGINX to feeding PHP FPM non php script file
# (like uploaded image)
# 不能用 "try_files $uri =404;", 因為底有另一個 "if"
if (!-f $document_root$fastcgi_script_name) { return 404; }
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
# disallows the FPM to process files in the /uploads/ directory
if ($uri !~ "^/uploads/") {
# fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_pass php56-fpm;
}
}
snippets/common.conf
location ~ /\. { deny all; }
location = /favicon.ico { log_not_found off; access_log off; }
location = /robots.txt { log_not_found off; access_log off; }
# disallows access php in ? folder
location ~* /(?:uploads|files)/.*\.php$ { deny all; }
# no php is touched for static content, 因為中了 "$uri" 或 "$uri/"
location / { try_files $uri $uri/ /index.php?$args; }
sites-enabled/datahunter.org.conf
# vhost 設定 upstream php56-fpm { server 127.0.0.1:9056; } server { server_name datahunter.org www.datahunter.org; listen 80; root /home/vhosts/datahunter.org/public_html; index index.php index.html index.htm; ... # Protect admin panel location ~ ^/(wp-admin|wp-login\.php) { auth_basic "Restricted"; auth_basic_user_file htpasswd; } ... include snippets/common.conf; include snippets/php56-fpm.conf; }
Status page config in Nginx
Setting:
location ~ ^/(status|ping)$ { access_log off; allow 127.0.0.1; deny all; include fastcgi_params; fastcgi_pass 127.0.0.1:9000; }
查看 status
curl -k https://owncloud.datahunter.org:8443/status
pool: www
process manager: dynamic
start time: 03/May/2014:09:29:47 +0000 # started or reloaded
start since: 110
accepted conn: 12
listen queue: 0
max listen queue: 0
listen queue len: 128
idle processes: 3
active processes: 1
total processes: 4
max active processes: 1
max children reached: 0 # 多少次到達了 children limit
listen queue
The number of request in the queue of pending connections.
If this number is non-zero, then you better increase number of process FPM can spawn.
listen queue len
the size of the socket queue of pending connections
total processes (idle + active)
The current total number of processes.
max listen queue # since FPM has started
The maximum number of requests in the queue of pending connections
max active processes # since FPM has started
the maximum number of active processes since FPM has started
slow requests
The total number of requests that have hit the configured request_slowlog_timeout
output
# short status
- /status
- status?json
- /status?html
- /status?xml
# full status
- /status?full
- /status?json&full
- /status?html&full
- /status?xml&full
Status page on Apache
# RHEL
conf.d/php-fpm-status.conf
<LocationMatch "/status"> Require ip 127.0.0.1 # Require ip 1.2.3.4 # Your IP here # Adjust the path to the socket if needed #ProxyPass "unix:/run/php-fpm/www.sock|fcgi://localhost/status" ProxyPass "fcgi://localhost:9080/php-fpm-status" </LocationMatch> <LocationMatch "/ping"> Require ip 127.0.0.1 # Require ip 1.2.3.4 # Your IP here # Adjust the path to the socket if needed #ProxyPass "unix:/run/php-fpm/www.sock|fcgi://localhost/ping" ProxyPass "fcgi://localhost:9080/php-fpm-ping" </LocationMatch>
php-fpm.conf
ping.path = /php-fpm-ping pm.status_path = /php-fpm-status
Test
- curl localhost/php-fpm-ping
- curl localhost//php-fpm-status
fastcgi setting
fastcgi_intercept_errors
fastcgi_intercept_errors on; # Default: off
Determines whether FastCGI server responses with codes
greater than or equal to 300 should be passed to a client or
be intercepted and redirected to nginx for processing with the error_page directive.
fastcgi_split_path_info
Syntax: fastcgi_split_path_info regex;
The fastcgi_split_path_info regex capable to correctly handle request like
- /test.php/foo/blah.php
- /test.php/
first regex capture: becomes a value of the $fastcgi_script_name
second regex capture: becomes a value of the $fastcgi_path_info
i.e.
Setting
fastcgi_split_path_info ^(.+?\.php)(/.*)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info;
request "/show.php/article/0001"
$fastcgi_script_name = first = /show.php
$fastcgi_path_info = second = /article/0001
php.ini - cgi.fix_pathinfo
cgi.fix_pathinfo (Default: 1)
# 修改
sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' /etc/php.ini
# Checking
test.php
<?php var_export($_SERVER)?>
* Pay attention to the value of
- REQUEST_URI,
- SCRIPT_FILENAME,
- SCRIPT_NAME,
- PATH_INFO, PHP_SELF
Request: /path/to/script.php/THIS/IS/PATH/INFO
[1]
PATH_INFO = /THIS/IS/PATH/INFO
SCRIPT_FILENAME = /path/to/script.php
[0]
make PHP_SELF variable broken (not equal to DOCUMENT_URI).
Remark
現在已很小要修改 cgi.fix_pathinfo 了, 因為 php 有 security.limit_extensions
security.limit_extensions 會限制了 php(process) 執行那些檔案
/etc/php-fpm.d/www.conf
# Default Value: .php security.limit_extensions = .php
.user.ini
要放在 public_html 才有效 !! (public_html/.user.ini)
由於它是放在 public_html 內, 所以要用 .htaccess 保護它 (public_html/.htaccess)
<Files ".user.ini"> Require all denied </Files>
.user.ini
short_open_tag=On memory_limit=256M upload_max_filesize=50M post_max_size=60M date.timezone=Asia/Hong_Kong session.gc_maxlifetime=3600 max_execution_time=60 error_reporting=E_ALL & ~E_WARNING & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE
Notes: 不支援的 Settings
- expose_php=Off
有關 .user.ini 的 php.ini Settings
user_ini.cache_ttl 300 user_ini.filename .user.ini