實體主機程式崩潰診斷:驗證核心傾印的擷取流程

實體主機程式崩潰診斷:驗證核心傾印的擷取流程

實體主機程式崩潰診斷:驗證核心傾印的擷取流程

業務程序突然終止時,重新啟動服務只能恢復運作,無法解釋崩潰原因。如果日誌只留下訊號編號,還需要崩潰當下的呼叫堆疊與對應建置,才能定位問題。本文在 Ubuntu Server 24.04 上建立受控的核心傾印擷取流程,先以隔離程序完成驗收,再決定是否為業務服務啟用。

AMDSSH 實體主機可選用 128GB 或 256GB ECC 記憶體,但不應依整機容量無條件保存程序傾印。core 檔案可能包含密碼、請求本文與業務資料;擷取範圍、容量限制及存取權限必須一併設定。

一、確認崩潰類型與現有收集器

付款後,在控制台查看連線憑證,並透過 SSH 登入。以下操作需要管理員權限;測試前先確認系統、磁碟空間與核心傾印的處理入口:

cat /etc/os-release
df -h /var/lib
sysctl kernel.core_pattern
sudo journalctl -b -p warning --no-pager

當 kernel.core_pattern 以豎線開頭時,核心會將傾印交給使用者空間的處理程式,而不是直接寫入目前目錄。系統可能已安裝其他崩潰收集器,必須記錄原始設定值與相關套件,不能疊加兩套處理入口後就假定兩者都能正常運作。

先區分主動結束、訊號終止與記憶體不足導致的程序終止。SIGSEGV、SIGABRT 通常會觸發核心傾印,SIGKILL 則不會。服務狀態顯示異常終止,不代表已產生可下載的檔案。

core dump 是程序記憶體的證據,不是一般執行日誌。不得放在公開目錄,也不應未經檢查就附加至支援案件或程式碼儲存庫。

安裝本文使用的工具;若套件管理員提示將取代現有收集器,應先確認影響,再明確選擇其中一種機制:

sudo apt-get update
sudo apt-get install systemd-coredump gdb gcc
sysctl kernel.core_pattern
systemctl status systemd-coredump.socket --no-pager

安裝後,處理入口應指向 systemd 的傾印處理程式。通訊端負責接收,處理服務則按需啟動;沒有常駐的擷取程序,不代表功能失效。

二、為擷取流程設定容量上限

建立 /etc/systemd/coredump.conf.d/60-controlled-capture.conf,寫入以下設定:

[Coredump]
Storage=external
Compress=yes
ProcessSizeMax=256M
ExternalSizeMax=256M
MaxUse=512M
KeepFree=2G

這是用於小型測試程序的驗收配額,不是高記憶體用量業務的建議值。ProcessSizeMax 限制可供處理的傾印大小,ExternalSizeMax 限制外部儲存的大小;超過限制時,可能只留下事件中繼資料,沒有完整的記憶體檔案。

MaxUse 與 KeepFree 用於控制外部傾印目錄的空間用量,不保證磁碟空間一定會被保留,也不控制日誌資料庫的容量。多個程序同時崩潰仍可能造成空間壓力,因此需要一併監控所在檔案系統的剩餘空間。

後續啟動的處理程序會讀取設定,可用以下命令核對合併後的結果:

systemd-analyze cat-config systemd/coredump.conf

為業務啟用前,應先量測具代表性的程序所用記憶體與實際傾印大小,再調整上限。不能因為測試程式通過驗收,就認為使用大量記憶體的資料庫也能完整保存傾印。

三、以隔離服務驗證實際崩潰

建置不含業務資料的測試程式

在 /tmp/crash-lab.c 寫入最小測試程式:

#include <stdlib.h>

int main(void)
{
    abort();
}

建立專用的系統帳號並編譯程式。-g 保留除錯資訊,-O0 則方便觀察測試呼叫堆疊:

sudo useradd --system --no-create-home --shell /usr/sbin/nologin crashlab
sudo install -d -m 0755 /usr/local/libexec
sudo gcc -g -O0 -o /usr/local/libexec/crash-lab /tmp/crash-lab.c

若帳號已存在,應先確認其用途,不要重複建立。接著建立 /etc/systemd/system/crash-lab.service:

[Unit]
Description=Isolated core dump capture test

[Service]
Type=oneshot
User=crashlab
ExecStart=/usr/local/libexec/crash-lab
LimitCORE=infinity
Restart=no

這裡的 infinity 只放寬測試服務的程序限制,收集器仍受上一節的配額約束。不要將它設成所有服務的全域預設值。

sudo systemctl daemon-reload
sudo systemctl start crash-lab.service
sudo systemctl status crash-lab.service --no-pager
sudo coredumpctl --no-pager list /usr/local/libexec/crash-lab

啟動命令回報失敗是預期結果。應能看到與測試執行檔相符的崩潰紀錄;若沒有,請依序檢查處理入口、服務限制、收集器日誌及磁碟空間,不要對正式環境中的程序傳送崩潰訊號。

四、驗收傾印檔案與除錯材料

從清單記下本次測試的 PID,在同一個管理員 shell 中輸入,將傾印匯出至專用的私人目錄:

sudo -i
read -r -p 'Crash PID: ' CRASH_PID
umask 077
install -d -m 0700 /root/crash-evidence
coredumpctl info "$CRASH_PID"
coredumpctl dump "$CRASH_PID" --output=/root/crash-evidence/test.core
gdb -q -batch \
  -ex 'set pagination off' \
  -ex 'thread apply all bt' \
  /usr/local/libexec/crash-lab /root/crash-evidence/test.core
exit

先核對事件時間、執行檔、訊號與儲存狀態,避免因 PID 重複使用而取錯紀錄。驗收結果應顯示 SIGABRT,且呼叫堆疊能對應到測試程式的 main;系統函式庫的堆疊框架缺少原始碼,並不影響測試流程的驗證。

如果只有中繼資料、檔案無法匯出,或出現截斷提示,都不能視為完整擷取成功。coredumpctl 能列出事件,也不保證外部檔案仍然存在。

實際業務還需要封存崩潰當下的執行檔、共用函式庫與對應的除錯符號。更新後的同名二進位檔不等於原始建置,可使用 readelf -n 核對 Build ID,並記錄套件版本與建置識別碼。

不要直接使用 bt full 輸出區域變數。先查看基本呼叫堆疊;確實需要檢查變數時,應在受限環境中操作,並逐項審查匯出的文字。複製二進位檔時也應保存雜湊值,避免分析期間材料遭到替換。

五、業務導入與撤銷驗收

為業務服務啟用時,透過該服務自己的 drop-in 設定 LimitCORE,執行 daemon-reload 後,再於受控變更中重新啟動服務。既有程序不會因設定檔修改而自動套用新限制,應檢查實際程序的 /proc/PID/limits。

導入檢查至少應包含四項:

測試結束後,刪除測試服務檔案、程式及原始碼,並執行 daemon-reload 與 reset-failed。測試傾印應依 coredumpctl info 顯示的實際路徑個別處理,不要使用萬用字元清空整個傾印目錄。

若要撤銷擷取策略,請移除本文新增的設定檔;若需恢復原有收集器,應透過套件設定還原,並再次核對 kernel.core_pattern,不能憑記憶拼湊處理入口。最後記錄一次完整驗收:崩潰事件可查詢、檔案可匯出、呼叫堆疊對應正確建置、材料存取受到限制。如此留下的才是可複核的故障證據,而不是無人驗證的開關。

常見問題

啟用核心傾印後,每次異常結束都會留下檔案嗎?

不會。程式主動結束與 SIGKILL 通常不產生傾印;可產生傾印的訊號也會受到程序限制、擷取策略、檔案大小及磁碟空間影響,應以隔離測試驗證完整流程。

GDB 能開啟傾印檔案,就代表診斷資料完整嗎?

不是。還須取得崩潰當時的執行檔、共用函式庫與除錯符號,並確認傾印未被截斷。呼叫堆疊必須能對應正確的建置版本。

EPYC 7543P 獨享實體主機每月 $450.2 起

從資源規劃到主機配置

機型與選配費用按月合計計算,完整明細請見配置頁;交付後可在控制台查看連線憑證。