如何診斷 Linux 上的 OOM 問題 文章首圖

如何診斷 Linux 上的 OOM 問題

如何診斷 Linux 上的 OOM 問題

在 Linux 系統管理中,Out of Memory (OOM) 錯誤是令人頭痛的問題之一。當系統記憶體耗盡時,Linux 核心的 OOM Killer 機制會強制終止某些進程以釋放資源。對於系統管理員而言,快速定位是哪個服務導致了記憶體洩漏或異常消耗,是恢復服務穩定性的關鍵。本文将以 Ubuntu 22.04 和 Debian 12 為基礎,為您提供一套循序漸進的診斷流程。

第一步:確認 OOM 事件是否發生

在深入分析之前,首先需要確認系統是否真的觸發了 OOM 事件。Linux 核心會在日誌中記錄相關訊息。您可以使用 dmesg 指令來檢視核心環形緩衝區(Kernel Ring Buffer)的內容。

請執行以下指令搜尋關鍵字 Out of memory

dmesg | grep -i "out of memory"

如果輸出結果中包含類似 Out of memory: Killed process 1234 (nginx) 的訊息,這表示核心確實終止了 PID 為 1234 的 nginx 進程。請特別注意最後的進程名稱,這通常是我們需要重點關注的目標。

此外,您也可以檢查系統日誌檔案,因為 dmesg 的內容在重啟後可能會消失。在 Ubuntu/Debian 系統上,可以使用 journalctl 來查詢:

journalctl -k | grep -i "oom-kill"

第二步:分析核心日誌以獲取詳細資訊

一旦確認了 OOM 事件,接下來需要找出「為什麼」會發生。核心在終止進程前,會輸出一段詳細的記憶體狀態報告。這段報告包含了每個進程的 RSS(實體記憶體使用量)、VMSZ(虛擬記憶體大小)以及其他關鍵指標。

請使用以下指令提取最近一次的 OOM 報告:

dmesg | grep -A 20 "Out of memory"

在輸出內容中,請特別關注 Task and memory cgroup stats 區塊。這裡會列出所有受影響進程的記憶體使用情況。通常,被標記為 oom_score 最高的進程就是被核心選中殺死的對象。oom_score 是一個介於 0 到 1000 的數值,數值越高代表該進程被終止的機率越大。

第三步:即時監控記憶體使用情況

為了防止問題再次發生,或者在問題發生時捕捉瞬間的記憶體尖峰,我們需要能夠即時監控記憶體狀態。Linux 提供了多種工具,其中 tophtop 是最直觀的選擇。

如果您尚未安裝 htop,可以先透過套件管理器安裝:

sudo apt update
sudo apt install htop

執行 htop 後,您可以觀察 Memory 欄位。如果發現某個特定進程的記憶體使用量持續增長而不釋放,這極可能是記憶體洩漏(Memory Leak)的跡象。對於更精確的監控,可以使用 smem 工具來查看換頁(Swap)和真實記憶體的使用情況:

sudo apt install smem
sudo smem -t -k -s swap

第四步:檢查 Swap 配置與核心參數

有時 OOM 問題並非因為物理記憶體不足,而是因為 Swap 分區配置不當或核心參數影響了記憶體分配策略。

首先,確認 Swap 是否已啟用:

free -h

如果 Swap 大小為 0 且系統記憶體緊迫,核心會更傾向於立即觸發 OOM Killer。建議為伺服器配置適當的 Swap 空間。

此外,您可以調整核心的 vm.swappiness 參數,控制系統使用 Swap 的積極程度。預設值通常為 60,降低此值可以讓系統更傾向於保留實體記憶體而非使用 Swap,這在某些情況下可以延緩 OOM 的發生:

# 查看當前值
cat /proc/sys/vm/swappiness

# 臨時調整為 10(重啟後失效)
sudo sysctl vm.swappiness=10

常見問題與解決方案

1. 如何防止重要服務被 OOM Killer 終止?

您可以調整特定進程的 oom_score_adj 值。該值的範圍是 -1000 到 1000。預設為 0。將其設為負值可以降低該進程被終止的優先級,設為 -1000 則完全禁止核心終止該進程(請謹慎使用,以免導致系統完全當機)。

例如,防止 Nginx 被終止:

echo -500 | sudo tee /proc/$(pidof nginx)/oom_score_adj

2. 為什麼 dmesg 找不到 OOM 訊息?

如果您在 dmesg 中找不到相關訊息,可能是因為日誌緩衝區已滿,或者系統日誌服務(如 rsyslog 或 systemd-journald)未正確記錄核心訊息。請檢查 /var/log/kern.log/var/log/syslog。如果這些檔案中依然沒有紀錄,可能是因為系統在 OOM 發生時已經無法寫入磁碟,此時唯一的方法是依賴監控工具(如 Prometheus + Node Exporter)的事前預警。

小結

診斷 Linux 上的 OOM 問題需要結合日誌分析、即時監控和核心參數調整。透過 dmesg 確認事件,利用 htop 觀察趨勢,並適當調整 oom_score_adj 和 Swap 配置,您可以有效減少服務中斷的風險。建議在生產環境中部署完善的記憶體監控系統,以便在 OOM 發生前發出預警,從而被動處理轉為主動預防。