Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學

Linux 磁碟空間「失蹤」三大元兇:隱藏檔、掛載遮蓋、稀疏檔深度排查

編輯:Linux 系統常見問題解答

明明 df -h 顯示分區 95% 滿載,du -sh /* 卻只加總到 60% —— 這 35% 去哪了?本文針對 Linux 磁碟空間「失蹤」的三大經典成因,提供定位指令、原理圖解與一鍵清理腳本。

現象對比

# df 看分區用量
Filesystem  Size  Used Avail Use% Mounted on
/dev/sda1   100G   90G   5G  95%  /

# du 看目錄佔用(根目錄)
du -sh /* 2>/dev/null | sort -hr
# 總和僅 60G,少了 30G!

元兇一:隱藏檔案/目錄

du -sh * 的 * 不會匹配以 . 開頭的隱藏項。常見場景:/root/.cache、/var/spool/mail/.*、/tmp/.ICE-unix、應用程式寫入的 ./.large_temp。

定位指令

# 只統計隱藏項
du -sh .[^.]* 2>/dev/null | sort -hr

# 完整掃描(含隱藏)
du -sh /* .[^.]* 2>/dev/null | sort -hr

元兇二:非空目錄被掛載遮蓋

原目錄 /data 已有 20G 檔案,執行 mount /dev/sdb1 /data 後,原檔案被新檔案系統「遮蓋」,du 看不見,但 inode 仍佔用空間,df 仍計入。

定位指令

# 找出所有掛載點
findmnt -rn -o TARGET,SOURCE,FSTYPE | while read mnt src fs; do
  # 比較掛載前後 inode 數(需掛載前基線)
  echo "=== $mnt ($src) ==="
  ls -la "$mnt" | head -5
done

# 快速檢測:同一 inode 出現在多個掛載點
find / -xdev -printf '%i %p\n' 2>/dev/null | sort -k1,1n | uniq -D -w 10

恢復方法

umount /data          # 解掛載
ls -la /data          # 原檔案重現
mv /data/* /backup/   # 遷移資料
mount /dev/sdb1 /data # 重新掛載
mv /backup/* /data/   # 寫回新檔案系統

元兇三:稀疏檔 / 已刪除但未釋放的檔案

進程持續寫入 app.log,運維執行 > app.log 清空內容。因檔案描述符(fd)仍被進程持有,inode 不釋放,磁碟空間不歸還;ls -lh 顯示 0,du 統計 0,但 df 仍計佔用。

定位指令

# 找出已刪除但仍被持有的檔案
lsof -nP | grep '(deleted)'

# 輸出範例
java    1234 user  10u   REG  253,0  10G  12 /var/log/app.log (deleted)

# 釋放空間(不重啟進程)
: > /proc/1234/fd/10   # 透過 /proc 截斷 fd 指向的 inode

一鍵診斷腳本

#!/bin/bash
# disk_lost.sh — 快速定位空間失蹤原因
echo "=== 1. 隱藏項佔用 ==="
du -sh /.[^.]* 2>/dev/null | awk '$1+0>100' | sort -hr

echo -e "\n=== 2. 掛載點遮蓋疑點 ==="
findmnt -rn -o TARGET | while read mnt; do
  if [ -d "$mnt" ] && [ "$(ls -A "$mnt" 2>/dev/null | wc -l)" -gt 0 ]; then
    echo "⚠ $mnt 非空,可能被遮蓋"
  fi
done

echo -e "\n=== 3. 已刪除未釋放檔案 ==="
lsof -nP | awk '/\(deleted\)/{print $1,$2,$9,$10}' | sort -k4 -hr | head -20

預防最佳實踐

  • ✅ 重要目錄(/var/log, /data, /opt)採用獨立分區/邏輯卷,避免根分區被單一應用填滿
  • ✅ 掛載前強制檢查目錄是否為空:mount --bind /empty /target && mount /dev/sdb1 /target
  • ✅ 日誌輪轉用 logrotate + copytruncate 或 systemd-journald,避免 > file 產生稀疏檔
  • ✅ 監控系統加入 df -i(inode 耗盡同樣導致無法寫入)

結語: 空間失蹤 90% 以上屬於上述三類。下次遇到 df 與 du 對不上,先跑 lsof | grep deleted、再查隱藏項、最後核對掛載點,通常 5 分鐘內鎖定元兇。

Copyright © Windows教程網 All Rights Reserved