跳到主內容

Linux 磁碟空間排查與清理標準作業流程 (SOP)

階段一:快速定位受影響磁碟分割區快速確認整體磁碟狀態 (Filesystem)Filesystem Check)

在進入目錄細查前,先確認是磁碟容量不足還是 Inode 耗盡:

Bash
# 1. 檢視各磁碟掛載點空間使用率檢查各掛載點空間使用率 (以人類可讀單位顯示)以 GB/MB 顯示)
df -h

# 2. 檢查 Inode 使用率 (避免容量未滿但若使用率達 Inode100% 耗盡導致無法寫入)即使空間充裕也無法寫入新檔)
df -i

階段二:由大到小逐層定位目錄與檔案逐層下鑽定位高佔用目錄 (Drill-Down)Down 核心流程)

排查關鍵在於加上 -x(--one-file-system)參數,強制不跨越其他掛載點與虛擬檔案系統(自動跳過 /proc、/sys、/dev 及外部 NFS/掛載磁區),大幅提升速度並避免報錯。

1.步驟 檢查根目錄或特定目錄下各子目錄大小1:掃描根目錄 (/) 最大的第一層目錄

Bash
# 檢查第一層目錄容量並排序 (排除 proc/sys 等虛擬檔案系統報錯)sudo du -hxh --max-depth=1 / 2>/dev/null | sort -hr | head -n 20

# 包含隱藏目錄/檔案 (適用於家目錄排查,如 /home/user)
du -sh /home/tomcat/{.[!.],}* 2>/dev/null | sort -hr | head -n 15
依結果判定主要元兇位於哪一個分支(通常為 /var、/home 或 /data)。

步驟 2:進入目標大目錄向下鑽取 (Drill-Down)

假設發現 /home 佔比最高,接續檢查 /home 內部使用者:

Bash
sudo du -xh --max-depth=1 /home 2>/dev/null | sort -hr | head -n 15

2.步驟 跨層級搜尋超大檔案3:進入特定使用者目錄(自動涵蓋隱藏檔 (Top Large Files)Dotfiles)

假設發現 /home/gitlab-runner 或 /home/tomcat 偏大,直接指定路徑即可自動列出所有一般與隱藏資料夾(無需使用易爆掉的 glob 語法):

Bash
# 列出指定目錄下最大的前 10 個檔案
find /path/to/target -type f -execsudo du -hxh {}--max-depth=1 +/home/gitlab-runner 2>/dev/null | sort -hr | head -n 10

# 搜尋大於 500MB 或 1GB 的單一檔案
find / -type f -size +500M -exec ls -lh {} + 2>/dev/null15

階段三:常見高佔用項目清理語法

1.步驟 應用程式快取與依賴套件4:跨目錄直接找出 Top 10 超大單一檔案

    若目錄層級過深,可直接搜尋該目錄樹下體積最大的前 10 個實體檔案:

    Bash
    sudo find /home/gitlab-runner -xdev -type f -exec du -h {} + 2>/dev/null | sort -hr | head -n 10
    
    NPM維護人員捷徑(可加入 Cache~/.bashrc):

    Bash
    #duck() 透過{ npmsudo 工具清空du npm cache clean-xh --forcemax-depth=1 #"${1:-.}" 若無指令或強制刪除實體檔案2>/dev/null rm| sort -rfhr ~/.npm/_cacache/*| head -n 15; }
    
    Yarn使用方式:duck / → duck /home → duck /home/tomcat

    階段三:高佔用目標清理標準語法

    1. 套件依賴與建置快取 (NPM / PnpmPackage Cache:

    Cache)
    Bash
    yarn cache clean
    pnpm store prune
    

    2. 日誌檔案 (Logs)

    重要原則:運作中的服務日誌切勿直接 rm,否則因 Process 持有 File Descriptor,磁碟空間不會釋放(見階段五)。應使用 truncate 清空內容。

      PM2 Logs:

      Bash
      pm2 flush
      
      傳統 Application / Nginx / Tomcat 日誌:

      Bash
      # 將日誌內容清空為NPM 0-byte快取:以原帳號或 (安全作法)root truncate清理
      npm cache clean -s 0 /path/to/logfile.log-force
      # 或使用或實體刪除快取目錄
      shellrm 重導向-rf :~/.npm/_cacache/*
      >sudo rm -rf /path/to/logfile.loghome/gitlab-runner/.npm/_cacache/*
      
      # Yarn / Pnpm 快取
      yarn cache clean
      pnpm store prune
      
      Systemd Journal 日誌:

      Bash
      # 僅保留最近 7 天的 journal
      journalctl --vacuum-time=7d
      
      # 或限制 journal 總量上限在 500MB
      journalctl --vacuum-size=500M
      

      3. 容器與 CI/CD 建置暫存 (Docker / GitLab Runner)

        Docker 清理:

        Bash
        # 清理停止的容器、未使用的網路與 Dangling 映像檔
        docker system prune -f
        
        # 深度清理:包含未使用的 Volumes 與 Build Cache
        docker system prune -a --volumes -f
        
        # 單獨清理 Buildx 建置快取
        docker builder prune -a -f
        
        GitLab Runner 快取:

        Bash
        # 清空 runner 的 builds 與 cache 目錄
        rm -rf /home/gitlab-runner/cache/*
        rm -rf /home/gitlab-runner/builds/*
        

        4. 系統套件庫快取 (OS Package Manager)

          Debian / Ubuntu (APT):

          Bash
          sudo apt-get clean
          sudo apt-get autoremove -y
          
          RHEL / CentOS / Rocky Linux (YUM / DNF):

          Bash
          sudo dnf clean all
          # 或
          sudo yum clean all
          

          階段四:清理命令誤觸留下的異常檔案 (0-Byte 殘留)

          常見於 curl 或 wget 語法錯誤時產生的 HTTP Header 檔名:

          Bash
          rm -f ./Accept: ./GET ./Host: ./User-Agent: ./--header
          

          階段五:特殊狀況排查(刪了檔案空間卻未釋放)

          2. CI/CD 與容器環境 (GitLab Runner / Docker)

          若 rm
          刪除大檔後
          df
          -h 空間依然未釋放,表示該檔案仍被運行中的行程開啟中(Deleted Handle)。
          Bash
          # 1.GitLab 查詢處於Runner deleted專案建置與暫存目錄
          狀態但被行程佔用的檔案rm lsof-rf +L1/home/gitlab-runner/cache/*
          rm -rf /home/gitlab-runner/builds/*
          
          # 或Docker lsof容器/映像檔清理
          |docker grepsystem '(deleted)'prune -f
          
          # 2.Docker 解決方式:Buildx #建置快取清理
          A.docker 重啟持有該檔案的服務builder (最佳實踐)prune systemctl-a restart <service_name>
          
          # B. 若無法中斷服務,直接對該 Process 的 File Descriptor 進行清空
          # 假設 PID 為 12345,FD 為 3
          : > /proc/12345/fd/3-f
          

          階段六:驗證結果

          3. 服務日誌安全清理 (Logs Truncate)

          防踩坑準則:運行中的服務日誌切勿直接 rm。若行程未釋放 File Descriptor,磁碟空間將不會釋放。應採用 truncate 或重導向清空。

          Bash
          # PM2 日誌清理
          pm2 flush
          
          # Nginx / Tomcat / App 日誌安全截斷為 0-byte
          truncate -s 0 /path/to/catalina.out
          # 或使用 shell 內建清空語法
          : > /path/to/access.log
          
          # Systemd Journal 系統日誌清理 (保留最近 7 天或限額 500MB)
          journalctl --vacuum-time=7d
          journalctl --vacuum-size=500M
          

          4. 系統套件庫暫存 (OS Package Cache)

          Bash
          # Ubuntu / Debian
          sudo apt-get clean
          sudo apt-get autoremove -y
          
          # RHEL / CentOS / Rocky Linux
          sudo dnf clean all || sudo yum clean all
          

          5. 腳本/測試誤觸留下的 0-Byte 異常檔案

          Bash
          # 清理 curl/wget 遺漏引號造成的 HTTP Header 殘留檔案
          rm -f ./Accept: ./GET ./Host: ./User-Agent: ./--header
          

          階段四:刪檔後空間未釋放排查 (Deleted Handle)

          若執行 rm 刪除超大日誌檔後,df -h 空間依然居高不下,代表該檔案仍被背景 Process 開啟著。
          Bash
          # 1. 查詢處於 deleted 狀態但仍被 process 佔用的檔案
          sudo lsof +L1
          # 或
          sudo lsof | grep '(deleted)'
          
          # 2. 處置方式:
          # 方案 A:重啟持有該檔案的行程/服務 (最推薦)
          sudo systemctl restart <service_name>
          
          # 方案 B:無法重啟時,透過 /proc 直接釋放 (假設 PID=12345, FD=3)
          : > /proc/12345/fd/3
          

          階段五:驗證

          Bash
          # 1. 確認分割區可用容量
          df -h
          
          # 2. 驗證特定目錄剩餘大小
          du -sh /home/gitlab-runner
          
          # 再次檢視掛載點容量是否下降
          df -h
          
          # 驗證特定目錄清理後的容量
          du -sh /path/to/target