by Rain Chu | 2 月 11, 2026 | PHP, 程式
最近我的伺服器突然出現網站 502 錯誤,檢查後發現 php8.2-fpm 服務竟然被系統強制終止。透過一系列排查,最終確認是 Linux OOM Killer(Out Of Memory) 觸發導致。
這篇文章整理完整排查過程與解決方案,提供給遇到相同問題的人參考。
📌 問題現象
使用 systemctl status php8.2-fpm 發現:
Active: failed (Result: oom-kill)
進一步檢查 kernel log:
Out of memory: Killed process 7057 (php-fpm8.2)
anon-rss:283560kB
shmem-rss:119848kB
代表:
- 系統記憶體耗盡
- Linux 啟動 OOM Killer
- 強制殺掉 php-fpm worker
🔍 進一步分析
查看當時 PHP worker 記憶體使用情況:
ps -o pid,rss,etime,cmd -C php-fpm8.2 --sort=-rss | head -n 20
當時結果顯示:
RSS 約 250MB ~ 325MB/每個 worker
而之前狀態顯示:
Processes active: 80
idle: 0
🔥 問題核心
如果每個 worker 約 300MB:
但機器只有:
👉 記憶體一定會爆。
🧠 伺服器環境
這代表:
- 沒有 swap 作為緩衝
- 一旦瞬間記憶體尖峰,直接 OOM
🛠 解決方案
✅ 1️⃣ 建立 8GB Swap(防止再次 OOM)
sudo fallocate -l 8G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
確認:
結果:
建議調整 swappiness
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.conf
sudo sysctl -p /etc/sysctl.d/99-swappiness.conf
✅ 2️⃣ 調整 PHP-FPM 設定(關鍵)
編輯:
/etc/php/8.2/fpm/pool.d/www.conf
修改為:
pm = dynamic
pm.max_children = 25
pm.start_servers = 6
pm.min_spare_servers = 4
pm.max_spare_servers = 10
pm.max_requests = 500
為什麼設 25?
假設每個 worker 約 150MB:
在 15GB RAM 環境下非常安全。
✅ 3️⃣ 開啟 Slow Log(抓出慢請求)
在 www.conf 加入:
request_slowlog_timeout = 10s
slowlog = /var/log/php8.2-fpm/www-slow.log
request_terminate_timeout = 60s
建立目錄:
sudo mkdir -p /var/log/php8.2-fpm
sudo chown -R www-data:www-data /var/log/php8.2-fpm
sudo systemctl restart php8.2-fpm
查看慢請求:
sudo tail -f /var/log/php8.2-fpm/www-slow.log
📊 調整後效果
重啟後查看:
ps -o pid,rss,etime,cmd -C php-fpm8.2 --sort=-rss | head -n 20
結果:
RSS 約 100MB ~ 170MB
ELAPSED 僅 20 秒左右
✔ 不再出現 300MB 以上肥 worker
✔ 不再出現 active 80
✔ 系統穩定運作
🎯 問題總結
本次 OOM 原因:
pm.max_children 設定過高
- 每個 worker 記憶體使用偏高
- 沒有 swap 緩衝
- 慢請求導致 worker 堆積
最終解法:
- 限制 max_children
- 建立 swap
- 開 slowlog 抓慢請求
- 設定 max_requests 避免 memory leak
🚀 建議最佳實務
| 設定 | 建議 |
|---|
| Swap | 一定要有(至少 4GB) |
| max_children | 用 RAM / worker RSS 計算 |
| max_requests | 300~1000 |
| slowlog | 必開 |
| request_terminate_timeout | 必設 |
📌 結論
OOM Killer 不是錯誤,它是保護機制。
真正的問題通常是:
- PHP-FPM 設定不合理
- 慢請求堆積
- 記憶體容量與負載不匹配
只要正確限制 worker 數量並建立 swap,伺服器穩定度會大幅提升。
如果你也遇到 php-fpm 被 OOM kill 的問題,希望這篇實戰紀錄能幫助你快速排查與解決。
相關資訊
by Rain Chu | 2 月 6, 2024 | GCP, Linux, MIS, Ubuntu, 未分類
在Ubuntu中要分享硬碟給另一台電腦,通常有兩種方法:使用網絡文件系統(NFS)與 Linux 或使用 Samba 與 Windows 共享。
以下是這兩種方法的步驟:
方法1:使用NFS(適合Linux系統)
安裝NFS服務器:
在提供共享的電腦上,打開終端並輸入以下命令安裝NFS服務器:
sudo apt update
sudo apt install nfs-kernel-server
配置共享目錄:
編輯/etc/exports文件來添加你想要共享的目錄。例如,如果你想共享/srv/nfs目錄,可以添加如下行:
/srv/nfs *(rw,sync,no_subtree_check)
其中*表示所有人都可以訪問,rw表示讀寫權限,sync表示同步寫入硬碟,no_subtree_check是速度比較快的選項。
重啟NFS服務:
sudo systemctl restart nfs-kernel-server
在客戶端電腦上安裝NFS客戶端
sudo apt install nfs-common
掛載共享目錄:
sudo mount server_ip:/srv/nfs /mnt
記得把 server_ip 換成你分享主機的 IP
方法2:使用Samba(適用於Windows和Linux系統)
安裝Samba:
在提供共享的電腦上,安裝Samba:
配置Samba共享:
輯Samba配置文件/etc/samba/smb.conf,在文件末尾添加如下配置:
sudo nano /etc/samba/smb.conf
[ShareName]
path = /srv/samba
read only = no
browsable = yes
請記得替換 ShareName 為你的共享名,/srv/samba 為你想共享的目錄。
重啟Samba服務:
sudo systemctl restart smbd
在另一台Ubuntu上訪問Samba共享:
可以在文件管理器的地址欄輸入 smb://server_ip/ShareName 來訪問共享,其中 server_ip 是Samba服務器的IP地址,ShareName是你設置的共享名。
Windows 上則是用檔案總管,並且在文字框內輸入 \\server_ip\ShareName
no_subtree_check 參數說明
no_subtree_check 是 NFS(網絡檔案系統)配置中的一個參數,用於改善NFS服務的性能。這個參數的作用與含義如下:
- 子樹檢查(Subtree Checking): 在NFS中,子樹檢查是一個安全特性,用來確保客戶端訪問的檔案仍然是它最初打開時的那個檔案。這是通過檢查檔案所在的目錄結構來實現的。如果檔案在檔案系統中被移動或重命名,NFS會通過子樹檢查來識別這些改變。
no_subtree_check 的作用: 啟用 no_subtree_check 參數會禁用這種子樹檢查。這意味著NFS服務器不會檢查檔案是否被移動或重命名。這樣做可以提高性能,因為減少了服務器的檢查負擔。在大多數情況下,這是安全的,特別是在檔案不太可能在訪問期間被移動或重命名的環境中。
- 應用場景: 在許多常規的NFS使用情況下,子樹檢查是不必要的,因為檔案的移動並不頻繁。在這些情況下,禁用子樹檢查可以提供更佳的性能表現,尤其是在處理大量的檔案請求時。
分享文件的安全性設定
要限制特定IP地址的主機才能连接NFS共享,您需要在NFS的配置文件 /etc/exports 中明确指定允许的IP地址。以下是具体步骤:
編輯/etc/exports檔案:
指定允許的IP地址:
在/etc/exports檔案中,您可以為每個共享目錄指定允許訪問的IP地址,我們要做的事情是把前面的*號替換成主機的IP。例如,如果您想只允許IP地址為192.168.1.100的主機訪問名為/srv/nfs的共享目錄,您可以這樣寫
/srv/nfs 192.168.1.100(rw,sync,no_subtree_check)
這行配置表示僅有IP地址為192.168.1.100的主機可以讀寫(rw)訪問/srv/nfs目錄。
您可以精確控制哪些IP地址的主機被允許訪問NFS共享。如果需要允許多個特定的IP地址,只需在/etc/exports檔案中的相應行裡添加這些IP地址,每個地址用空格分開。例如:
/srv/nfs 192.168.1.100(rw,sync,no_subtree_check) 192.168.1.101(rw,sync,no_subtree_check)
重啟NFS服務:
sudo systemctl restart nfs-kernel-server
開機時自動建立 NFS 連接
可以將 NFS 掛載點添加到客戶端主機的 /etc/fstab 文件中。/etc/fstab 文件用於在系統啟動時自動掛載文件系統。以下是一般步驟:
編輯 /etc/fstab 文件:
添加 NFS 掛載條目:
[NFS 伺服器 IP]:/[遠端共享目錄] [本地掛載點] nfs defaults 0 0
如果 NFS 伺服器的 IP 是 192.168.1.100,遠端共享目錄是 /exported/folder,本地掛載點是 /mnt/nfs,則添加:
192.168.1.100:/exported/folder /mnt/nfs nfs defaults 0 0
測試掛載: 為了檢查是否有語法錯誤,您可以手動掛載所有未掛載的 fstab 條目
其中在 /etc/fstab 文件中,每個掛載點的條目都包含一系列的字段,其中 defaults 0 0 是其中的兩個字段,意思如下
defaults: 這是掛載選項字段。defaults 代表一組預設的掛載選項。對於大多數文件系統,這包括了 rw(可讀寫)、suid(允許執行 suid 程序)、dev(解析字符和塊特殊裝置)、exec(允許執行二進制文件)、auto(允許自動掛載)、nouser(阻止普通用戶掛載文件系統)、和 async(進行異步 I/O)等選項。如果需要特定的選項,可以用逗號分隔,直接在這個位置列出。
- 第一個
0: 這是 dump 字段。dump 是一個備份實用程序,用來決定文件系統是否需要被備份。如果這個值設置為 0,則 dump 將忽略這個文件系統。如果設置為 1 或更高的數字,它表示文件系統的備份頻率。
- 第二個
0: 這是 fsck(文件系統檢查)的順序字段。這個數字決定了在啟動時檢查文件系統的順序。如果設為 0,系統啟動時將不會對這個文件系統進行 fsck 檢查。如果是根文件系統,這個值通常設為 1;其他文件系統則設為 2 或更高,或者保留為 0。
總的來說,defaults 0 0 是一個常見的配置,
要將掛載好的硬碟卸載的話
要卸載已經掛載的硬碟,您可以使用 umount 命令
確定掛載點:
卸載硬碟:
例如,如果硬碟掛載在 /mnt/mydisk,則命令為:
檢查卸載狀態:
可以再次使用 df -h 或 mount 命令來確認硬碟已經被卸載。
解決權限無法讀寫的問題
兩台主機間有不同的帳號,A主機帳號usera,B主機帳號userb,要再b主機修改a主機的資源的話,你會遇到無法執行的問題
可以選擇兩種策略
1.使用群組權限
如果 usera 和 userb 的 UID/GID 不同,您可以通過將它們都加入到同一個群組,並對該群組授予適當的權限來解決問題。
在 A 和 B 主機上創建相同的群組
sudo groupadd sharedgroup
將 usera 和 userb 添加到該群組:
在 A 和 B 主機上分別執行:
sudo usermod -a -G sharedgroup usera
sudo usermod -a -G sharedgroup userb
更改共享目錄的群組權限:
在 A 主機上設置共享目錄的群組為 sharedgroup,並確保群組具有讀寫權限:
sudo chown usera:sharedgroup /path/to/shared/directory
sudo chmod 2770 /path/to/shared/directory
2. 使用 NFS 伺服器選項映射 UID/GID
可以在 NFS 伺服器的 /etc/exports 文件中使用 all_squash, anonuid, 和 anongid 選項來映射所有客戶端用戶到特定的 UID 和 GID。
編輯 /etc/exports 文件
在 A 主機(NFS 伺服器)上編輯此文件,為共享目錄添加以下選項:
/path/to/shared/directory B主機的IP(rw,sync,no_subtree_check,all_squash,anonuid=UID,anongid=GID)
其中,將 UID 和 GID 替換為在 A 主機上 usera 的 UID 和 GID。
UID 和GID的查詢方法如下
就會取得像是 uid=0(root) gid=0(root) groups=0(root)
重啟 NFS 服務:
sudo systemctl restart nfs-server
這樣配置後,所有從 B 主機存取 A 主機共享目錄的操作都將以指定的 UID 和 GID 來執行,從而繞過 UID/GID 不匹配的問題。
GCP 連接外部硬碟
先看配置 df -h ,在用 lsblk 找出要配置的硬碟,通常在 GCP 中新掛的第一顆硬碟代號會是 sdb
如果是全新的硬碟要先格式化他
sudo mkfs.ext4 -m 0 -F -E lazy_itable_init=0,discard /dev/sdb
格式化後,可以開始準備掛載目錄,以及提升權限和下指令掛載
sudo mkdir -p /mnt/data
sudo chmod a+w /mnt/data
sudo mount -o discard,defaults /dev/sdb /mnt/data
最後記得要設定每次開機自動掛載,先用 blkid 找出硬碟的 UUID ,記錄下來後再把他填到 /etc/fstab 中
sudo blkid /dev/sdb
sudo nano /etc/fstab
將設定檔寫入 fstab
UUID=1535732s45-a52a-4e22-a258-7bsedgaw3e41 /mnt/data ext4 discard,defaults 0 2
存檔完畢後,測試一下是否有成功
延伸閱讀
近期留言