空垠尘

Linux 維運實戰排錯與疑難雜症手冊

引言:維運排錯的系統性心智模型

在 Linux 與 macOS 的日常維運中,我們總會遇到一些讓人措手不及的「靈異現象」:

  • 磁碟明明顯示還有幾十 GB 空間,寫入檔案卻提示 No space left on device;
  • 服務連接埠被佔用,卻查不到任何監聽行程;
  • 容器或後端服務莫名其妙被系統靜默殺死,沒有任何業務日誌;
  • 高併發場景下突然爆發大量 Too many open files 導致雪崩。

排錯不僅是敲幾條指令,更是順藤摸瓜的系統性推導過程。本文匯集一線維運中最高頻的 6 類疑難雜症,給出可直接落地的排查邏輯與根治方案。

flowchart TD
    Issue["系統異常與服務警報"] --> A["1. 檔案句柄耗盡<br/>(Too Many Open Files)"]
    Issue --> B["2. 磁碟爆滿/假滿<br/>(Inode 耗盡 / 句柄未釋放)"]
    Issue --> C["3. 連接埠衝突與殭屍行程<br/>(Address in use / Zombie)"]
    Issue --> D["4. 記憶體溢出被殺<br/>(Kernel OOM Killer)"]
    Issue --> E["5. 時鐘偏差與鑑權失效<br/>(Clock Skew / NTP 同步)"]
    Issue --> F["6. macOS 環境網路阻塞<br/>(Homebrew 源與網路排查)"]

一、 徹底解決 Too Many Open Files(檔案句柄耗盡)

在 Linux 與 macOS 哲學中,「一切皆檔案」。當併發連線數或開啟的檔案數超過系統預設限制時,就會拋出 Too many open files 錯誤。

1. Linux 生產環境徹底調優

① 修改系統級限制 (/etc/security/limits.conf)

1* soft nofile 655350
2* hard nofile 655350
3root soft nofile 655350
4root hard nofile 655350

② 修改 systemd 全域服務限制 (/etc/systemd/system.conf)

1[Manager]
2DefaultLimitNOFILE=655350
3DefaultLimitNPROC=655350

③ 查看當前行程佔用的句柄數

1ls /proc/<PID>/fd | wc -l

2. macOS 開發者環境調優

1# 查看當前限制
2launchctl limit maxfiles
3
4# 臨時增加限制 (當前終端機有效)
5sudo launchctl limit maxfiles 65536 200000
6ulimit -n 65536

二、 磁碟「假滿」與 Inode 耗盡 (No space left on device)

sequenceDiagram
    autonumber
    participant App as 應用程式 (如 Nginx / Java)
    participant Disk as 磁碟檔案 (/var/log/app.log)
    participant Admin as 維運工程師

    App->>Disk: 持續寫入大量日誌 (持有檔案句柄)
    Admin->>Disk: rm /var/log/app.log (刪除了檔名)
    Note over Disk: 空間無法釋放!因為 App 仍持有該句柄
    Admin->>App: 尋找未釋放句柄 (lsof | grep deleted) 並平滑重載
    Note over Disk: 磁碟空間瞬間恢復!

場景 A:檔案已被 rm 刪除,但行程仍持有句柄未釋放

1# 1. 尋找所有已被刪除但仍被行程佔用的檔案
2sudo lsof | grep -i deleted
3
4# 2. 優雅釋放空間(清空該行程對應的檔案描述符):
5sudo truncate -s 0 /proc/<PID>/fd/<FD>
6# 或平滑重載服務:sudo systemctl reload nginx

場景 B:磁碟空間充足,但 Inode(索引節點)耗盡

1# 1. 檢查 Inode 佔用率
2df -i
3
4# 2. 逐級統計哪個目錄下的小檔案最多
5find /var/spool/ -type d -exec sh -c "echo -n '{}: '; ls -1 '{}' | wc -l" \; | sort -n -k 2

三、 連接埠佔用衝突與殭屍行程清理

1. 連接埠佔用排查與一秒殺死

1# 1. 精準定位佔用 8080 連接埠的行程與 PID
2sudo lsof -i :8080
3# 或
4sudo ss -tulnp | grep :8080
5
6# 2. 強力一鍵釋放連接埠(自動殺死佔用者)
7sudo fuser -k 8080/tcp

2. 殭屍行程(Zombie Process)定位與清理

1# 1. 查看系統中的所有殭屍行程 (狀態為 Z)
2ps aux | grep 'Z'
3
4# 2. 尋找殭屍行程的父行程 PID (PPID)
5ps -o ppid= -p <ZOMBIE_PID>
6
7# 3. 優雅重啟或終止父行程,讓 init/systemd 回收殭屍
8sudo kill -HUP <PARENT_PID>

四、 行程靜默被殺:Linux 核心 OOM Killer 排查

1# 1. 檢查核心是否有 OOM 擊殺紀錄
2sudo dmesg -T | grep -i -E "oom|out of memory|killed process"

根治策略:

  1. 新增 Swap 交換分區:
    1sudo fallocate -l 2G /swapfile
    2sudo chmod 600 /swapfile
    3sudo mkswap /swapfile
    4sudo swapon /swapfile
    5echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
    
  2. 在 Docker / Kubernetes 中設定合理的記憶體 Limit。

五、 系統時鐘不同步導致 TLS/SSL 憑證與鑑權失效

1# 1. 檢查當前系統時間與 NTP 同步狀態
2timedatectl status
3
4# 2. 設定時區並開啟 NTP 自動同步
5sudo timedatectl set-timezone Asia/Taipei
6sudo timedatectl set-ntp true

六、 macOS 開發環境 Homebrew 映像加速與復原

 1# 1. 切換為開源映像源
 2export HOMEBREW_API_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/api"
 3export HOMEBREW_BOTTLE_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles"
 4export HOMEBREW_BREW_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git"
 5export HOMEBREW_CORE_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git"
 6
 7# 2. 恢復為官方預設源
 8unset HOMEBREW_API_DOMAIN
 9unset HOMEBREW_BOTTLE_DOMAIN
10export HOMEBREW_BREW_GIT_REMOTE="https://github.com/Homebrew/brew"
11export HOMEBREW_CORE_GIT_REMOTE="https://github.com/Homebrew/homebrew-core"
12brew update
文章目錄