PHP-FPM 是什麼 | 安裝與設定 PHP-FPM
PHP-FPM 是 FastCGI 程序管理員,由事先啟動好的工作程序接手網頁伺服器轉交過來的 PHP 請求並處理。本文在執行 Apache 的 AlmaLinux 9 伺服器上,確認是否已安裝,以及每個網站帳號的程序池(pool)與 socket 設定,並用實際輸出整理出設定檢查和狀態確認。
Apache 也可以用 mod_php 直接執行 PHP,但交給 PHP-FPM 之後,網頁伺服器和 PHP 就會分開。Nginx 無法直接執行 PHP,所以把請求交給 PHP-FPM 這類 FastCGI 程序。因此一個 PHP-FPM 不論接 Apache 還是 Nginx 都可以。下面的程序池設定與 socket 結構,在連接 PHP-FPM 和 Nginx 時也完全適用。
1️⃣ 什麼是 PHP-FPM:CGI 與 FastCGI 的差異
CGI(Common Gateway Interface)是網頁伺服器執行外部程式來產生動態內容的標準方式,每次有請求進來,就會重新啟動一次程式。每個請求都要建立再刪除程序,這個成本會不斷累積,連線越多,伺服器回應就越慢。
FastCGI 為了消除這個成本,事先把程式啟動好,再接連處理請求。這就像每次使用都要開機再關機,和直接使用一台已經開著的電腦之間的差別。PHP-FPM(FastCGI Process Manager)是以 FastCGI 方式執行 PHP 的管理員,從 PHP 5.3.3 版開始內建於 PHP。
PHP-FPM 會在每個程序池(工作程序的集合)中,事先啟動設定好數量的工作程序,閒置的工作程序接手網頁伺服器透過 socket 轉交的請求,處理完後等待下一個請求。圖片和 CSS 這類靜態檔案由網頁伺服器直接回應,只有 PHP 檔案會轉交給 PHP-FPM。不同的只有網頁伺服器把請求交給 socket 的方式:Apache 使用 mod_proxy_fcgi 模組,Nginx 使用 fastcgi_pass 設定。
2️⃣ 安裝 PHP-FPM:確認套件並用 dnf 安裝
如果在 RHEL 系列伺服器上用 dnf 安裝了 PHP,php-fpm 套件也會一起安裝。請先用 rpm 確認是否已安裝。PHP 的安裝過程與 Rocky Linux APM 安裝相同。
rpm -qa | grep php-fpmphp-fpm-8.3.36-1.module_php.8.3.el9.remi.x86_64如果輸出是空的,代表尚未安裝,請用 dnf 安裝。
dnf -y install php-fpm安裝完成後,再用同一個 rpm 指令確認是否輸出套件名稱。
3️⃣ 設定 PHP-FPM:www.conf 程序池與 socket、靜態與動態模式
設定檔有兩個:整體設定 [/etc/php-fpm.conf] 和程序池設定 [/etc/php-fpm.d/www.conf]。預設程序池 www.conf 要先看的行是 listen 和 pm,剛安裝完的值如下。
grep -E '^(listen|pm) ' /etc/php-fpm.d/www.conflisten = /run/php-fpm/www.sock
pm = dynamiclisten 是網頁伺服器轉交請求的位置,8.3 版的預設值是 Unix socket [/run/php-fpm/www.sock]。舊版本的預設值 [127.0.0.1:9000] 則是以 TCP 連接埠接收。在同一台伺服器內,socket 不必經過連接埠連線的過程,所以更輕量,還能用 listen.owner 和 listen.group 像檔案權限一樣限制存取。
🔲 設定靜態模式與動態模式
pm 是啟動工作程序的方式,從 static、dynamic、ondemand 三者中擇一指定。靜態模式會一直維持 pm.max_children 所填的數量,下面的設定會維持 100 個工作程序。
pm = static
pm.max_children = 100動態模式是預設值,會依請求量增減工作程序的數量。下面的設定在啟動時先啟動 12 個,閒置的工作程序維持在 6 個以上 18 個以下,最多增加到 120 個。
pm = dynamic
pm.max_children = 120
pm.start_servers = 12
pm.min_spare_servers = 6
pm.max_spare_servers = 18ondemand 模式只在請求進來時才啟動工作程序,經過 pm.process_idle_timeout 之後就結束,所以適合連線稀少的網站,不適合連線頻繁的網站。
這三種模式啟動工作程序的時機和增減方式各不相同。
| 模式 | 啟動工作程序的方式 | 適合的網站 |
|---|---|---|
| static(靜態) | 一直維持 pm.max_children 所填的數量 | 連線頻繁的網站 |
| dynamic(動態) | 預設值 · 依請求量在 pm.start_servers、pm.min_spare_servers、pm.max_spare_servers 範圍內增減 | 連線量時高時低的網站 |
| ondemand | 只在請求進來時啟動,經過 pm.process_idle_timeout 之後結束 | 連線稀少的網站 |
max_children 是用伺服器記憶體除以一個工作程序使用的記憶體來決定。即使 [max_children] 達到上限的警告不斷累積,也不要馬上調高,而是先 用日誌找出是哪些請求塞滿了工作程序.
記憶體和上傳上限在 PHP 整體設定 php.ini 中決定,要配合所經營的網站,連同工作程序數量一起調整。
memory_limit = 1024M
post_max_size = 128M
upload_max_filesize = 128M這三個值是單一 PHP 腳本可使用的記憶體上限,以及一次可以上傳的檔案大小,修改後必須重新啟動 PHP-FPM 才會生效。
🔲 設定各網站帳號的程序池
網站有多個時,不要共用同一個 www.conf,而是為每個帳號建立程序池檔案,分開執行帳號與 socket。一個網站的 PHP 讀不到其他帳號的檔案,工作程序的數量也能依網站分別決定。
vi /etc/php-fpm.d/siteuser.conf檔案裡要寫程序池名稱、執行帳號、socket 路徑和工作程序數量。
[siteuser]
user = siteuser
group = nobody
listen = /run/php-fpm/siteuser.sock
listen.owner = siteuser
listen.group = nobody
listen.mode = 0660
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
chdir = /home/siteuser/wwwlisten.owner 和 listen.group 是 socket 檔案的擁有者和群組,PHP-FPM 啟動時會用這些值建立 socket。網頁伺服器若以 nobody 帳號執行,就把 listen.group 寫成 nobody;若是 apache 帳號就寫 apache,讓網頁伺服器能開啟 socket。
listen.owner = siteuser
listen.group = nobody
listen.mode = 0660這三行會放在每個程序池檔案裡,修改值之後必須重新啟動,socket 才會以新的權限重新建立。
🔲 設定 slowlog
slowlog 是記錄耗時超過 request_slowlog_timeout 的請求執行位置的檔案,值為 0 時不記錄。要找出請求變慢的原因時,以 3s 這樣的秒數指定即可開啟。
slowlog = /var/log/php-fpm/www-slow.log
request_slowlog_timeout = 0記錄下來的檔案會保留慢請求的腳本路徑,以及當時正在執行的函式,因此能確認是哪個外掛或程式碼拖慢了時間。
4️⃣ 連接 Apache:VirtualHost 設定與 socket 權限
Apache 用 mod_proxy_fcgi 模組把 PHP 檔案的請求交給程序池的 socket。在 VirtualHost 內的 FilesMatch 放入一行 SetHandler,並為每個網站填入該帳號的 socket。
# 每個網站帳號一個 VirtualHost · SetHandler 填入該帳號的 socket(也可以用 ProxyPassMatch 代替 SetHandler 來連接)
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /home/siteuser/www
<Directory /home/siteuser/www>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php-fpm/siteuser.sock|fcgi://localhost"
</FilesMatch>
</VirtualHost>DocumentRoot 和 Directory 是該帳號的網站根目錄,Options 的 -Indexes 可避免資料夾清單在瀏覽器中顯示出來。
🔲 設定 socket 權限
程序池啟動時,會以 listen.owner、listen.group、listen.mode 的值建立 socket,再用 ls 確認權限是否正確。
ls -l /run/php-fpm/總計 4
srw-rw---- 1 siteuser_a nobody 0 10月 22 23:34 siteuser_a.sock
-rw-r--r-- 1 root root 7 10月 26 03:00 php-fpm.pid
srw-rw---- 1 siteuser_b nobody 0 10月 22 23:34 siteuser_b.sock
srw-rw----+ 1 root root 0 10月 22 23:34 www.sock權限不對、網頁伺服器無法開啟 socket 時,訪客會收到 503 錯誤,想不重新啟動就立刻調整,可用 chown 和 chmod 指定擁有者與權限。
這是用冒號分隔使用者和群組的目前語法。
chown siteuser:nobody /run/php-fpm/siteuser.sock變更擁有者之後,把權限調成 660。
chmod 660 /run/php-fpm/siteuser.sock這是用句點分隔使用者和群組的舊語法,在 AlmaLinux 9 的 chown 中也能照常執行。
chown siteuser.nobody /run/php-fpm/siteuser.sock變更擁有者之後,把權限調成 660。
chmod 660 /run/php-fpm/siteuser.sock兩種語法的結果相同,不論用哪一種,socket 的擁有者都會變成 siteuser,群組都會變成 nobody。
🔲 連接 Nginx:fastcgi_pass 設定
Nginx 在 server 區塊內處理 PHP 檔案的 location 中,用 fastcgi_pass 把請求交給同一個程序池的 socket。
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php-fpm/siteuser.sock;
}Nginx 若以 nginx 帳號執行,就要把程序池檔案的 listen.group 寫成 nginx,才能開啟 socket。
5️⃣ 設定檢查與重新啟動:php-fpm -t、systemctl
修改設定之後不要馬上重新啟動,要先用 php-fpm -t 做語法檢查。程序池檔案如果有打字錯誤,重新啟動時整個 PHP-FPM 會停掉,所有網站都會收到 503。
php-fpm -t[26-Oct-2026 17:33:45] NOTICE: configuration file /etc/php-fpm.conf test is successful檢查通過後,會連同設定檔路徑輸出 [test is successful] 訊息,接著再套用到 PHP-FPM。像 socket 路徑或 listen.owner 這類需要重新建立 socket 的變更,用 restart 套用。在營運中的伺服器上,如果只改了工作程序數量這類的值,就用 reload 套用。
systemctl restart php-fpm如果修改了 VirtualHost,也要重新啟動 Apache。
systemctl restart httpd用 enable 註冊,讓伺服器重新開機後自動執行。
systemctl enable php-fpm是否已註冊,可用 is-enabled 確認。
systemctl is-enabled php-fpmenabled用 status 確認每個程序池是否都有工作程序在運作。
systemctl status php-fpm● php-fpm.service - The PHP FastCGI Process Manager
Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; enabled; preset: disabled)
Active: active (running) since x
Process: 3934033 ExecReload=/bin/kill -USR2 $MAINPID (code=exited, status=0/SUCCESS)
Main PID: 1333314 (php-fpm)
Status: "Processes active: 4, idle: 21, Requests: x, slow: 0, Traffic: x"
Tasks: x
Memory: x
CPU: x
CGroup: /system.slice/php-fpm.service
├─ 41920 "php-fpm: pool siteuser_a"
├─ 94143 "php-fpm: pool siteuser_b"
├─1333314 "php-fpm: master process (/etc/php-fpm.conf)"
├─3934078 "php-fpm: pool www"
└─4009016 "php-fpm: pool siteuser_a"
10月 26 03:00:01 server.example.com systemd[1]: Reloading The PHP FastCGI Process Manager...
10月 26 03:00:01 server.example.com systemd[1]: Reloaded The PHP FastCGI Process Manager.Status 行的 active 和 idle 是目前正在處理請求的工作程序和閒置的工作程序,CGroup 則依程序池名稱列出工作程序。輸出中的主機名稱和程序池名稱已換成範例值。
🔢 FAQ & 推薦內容
ℹ️ 聯盟行銷說明
本站內容包含聯盟行銷連結。訪客透過這些連結購買商品或服務時,本站會從賣家獲得佣金。在這個過程中,購買者支付的金額(遇到活動折扣時金額會降低↓)並不會因此提高。刊登的價格、折扣與庫存資訊以撰寫當時為準,可能與實際情況不同,購買前請向賣家做最後確認。商品的挑選與評價依本站自訂的標準撰寫,是否支付佣金不會影響介紹順序或評價內容。