Linux伺服器磁碟空間佔用情況分析與清理指南

曾左發表於2024-09-27

為確保重大節日期間,團隊負責的測試環境伺服器磁碟不會佔用過高,導致頻繁報警。我們要求在重大節假日前對伺服器磁碟佔用情況進行檢查。如果發現佔用過高,則需人為介入,進行相應清理。

一、檢查要求

檢視各分割槽佔用情況,如果達到以下任一條件,則需要人為介入判斷或處理:

(1)磁碟使用率 > 90%

(2)磁碟使用 > 80% 且 剩餘空間 < 30G

(3)磁碟使用 > 70% 且 剩餘空間 < 50G

二、解決辦法

使用 shell 指令碼,統計並判斷磁碟佔用情況,如有異常,輸出異常資訊。

指令碼程式碼如下:

#!/bin/bash

RED='\033[0;31m'
NC='\033[0m'

if [[ $1 == "detail" ]]
then
    df -BG
else
    IS_NORMAL=1
    while read line
    do
        if [[ ${line} == Filesystem* ]]; then
            continue
        fi

        filesystem=$(echo ${line} | awk '{print $1}')
        use_rate=$(echo ${line} | awk '{print $5}' | sed 's/%//g')
        avail_space=$(echo ${line} | awk '{print $4}' | sed 's/G//g')
        mounted_on=$(echo ${line} | awk '{print $6}')

        if [[ ${use_rate} -gt 90 ]] || [[ ${use_rate} -gt 80 && ${avail_space} -lt 30 ]] || [[ ${use_rate} -gt 70 && ${avail_space} -lt 50 ]]; then
            echo -e "${RED}WARN: Filesystem ${filesystem} mounted on ${mounted_on} has problem: use rate is ${use_rate}%, available space is ${avail_space}G.${NC}"
            IS_NORMAL=0
        fi
    done < <(df -BG) 

    if [[ ${IS_NORMAL} -eq 1 ]]; then
        echo "INFO: Disk space usage is normal."
    fi
fi

關鍵程式碼說明:

df -BG :命令用於報告檔案系統的磁碟空間使用情況,-BG 選項表示以 G 位元組為單位顯示,B的含義為:use SIZE-byte blocks

建議指令碼儲存路徑:/data/sh/general/disk_usage_check.sh

初始化指令碼執行命令:mkdir -p /data/sh/general/;touch /data/sh/general/disk_usage_check.sh;chmod +x /data/sh/general/disk_usage_check.sh;vim /data/sh/general/disk_usage_check.sh

三、指令碼使用方法

1)根據檢查要求,判斷磁碟空間佔用是否存在佔用過多的情況

執行指令碼:/data/sh/general/disk_usage_check.sh

2)如由需要,可以進一步檢視各分割槽磁碟佔用資訊

執行指令碼:/data/sh/general/disk_usage_check.sh detail

使用示例,檢視結果,分兩種情況:

(1)檢查正常

[root@localhost ~]# /data/sh/general/disk_usage_check.sh 
INFO: Disk space usage is normal.

(2)檢查異常,檢視需要人為介入判斷及處理

[root@novalocal general]# /data/sh/general/disk_usage_check.sh 
WARN: Filesystem /dev/vdb mounted on /data has problem: use rate is 76%, available space is 47G.

[root@novalocal general]# /data/sh/general/disk_usage_check.sh detail
Filesystem              1G-blocks  Used Available Use% Mounted on
/dev/mapper/centos-root       49G   12G       38G  23% /
devtmpfs                       8G    0G        8G   0% /dev
tmpfs                          8G    1G        8G   1% /dev/shm
tmpfs                          8G    1G        7G  11% /run
tmpfs                          8G    0G        8G   0% /sys/fs/cgroup
/dev/vdb                     197G  142G       47G  76% /data
/dev/vda1                      1G    1G        1G  20% /boot
tmpfs                          2G    0G        2G   0% /run/user/0

處理方法可參考下一章節

四、佔用定位與解決辦法

1. 檢視目錄下各文給或資料夾大小,並降序輸出

[root@f2 data]# du -sh * | sort -hr
27G tomcat
5.1G did-generator
4.1G register
2.5G turbine-web
1.4G rbmq-productor
1.1G consul
600M backup
544M test-backup
527M deploy

命令解析:

du: 是 "disk usage" 的縮寫,這個命令用於估算檔案或目錄在磁碟上所佔用的空間。

-s: 這個選項告訴 du 命令僅顯示總計大小,而不列出每個子目錄或檔案的大小。

-h: 這個選項讓 du 以易讀的格式顯示大小(例如,自動選擇 KB、MB、GB 等單位)。

-r: 這個選項讓 sort 命令以降序排列結果(預設是升序)。

2. 為什麼刪除被佔用的檔案,不能釋放空間?

在 Linux 中,當你刪除一個檔案時,如果該檔案仍被某個程序所使用(即有一個開啟的檔案描述符指向這個檔案),那麼這個檔案的磁碟空間並不會被立即釋放。這是因為在 Linux 中,檔案的刪除實際上是刪除了檔名和 inode 的關聯,而不是刪除 inode 本身。只有當所有關聯到該 inode 的檔案描述符都被關閉後,該 inode 才會被刪除,對應的磁碟空間才會被釋放。

如果你刪除了一個仍被程序使用的檔案,你可以透過重啟程序或者重啟系統來確保所有的檔案描述符都被關閉,從而釋放磁碟空間。

可以使用 lsof 命令檢視該類檔案

(1)檢視被刪除但未釋放的檔案的命令:lsof | grep '(deleted)'

(2)檢視佔用空間最大的被刪除但未釋放的檔案:lsof | grep '(deleted)' | sort -n -r -k 7,7 | head -n 10,命令解析:

-n:以數值進行排序。預設情況下,sort 命令會以字串方式進行排序,但是 -n 選項會讓 sort 命令以數值方式進行排序。

-r:以逆序方式進行排序。預設情況下,sort 命令會以升序方式進行排序,但是 -r 選項會讓 sort 命令以降序方式進行排序。

-k 7,7:指定排序的欄位。預設情況下,sort 命令會以整行作為排序的依據,但是 -k 選項可以讓 sort 命令只以指定的欄位作為排序的依據。在這裡,-k 7,7 表示只以第7個欄位作為排序的依據。

五、遇到問題

1. 管道模式執行時,無法更新變數值

  IS_NORMAL=1
  df -BG | while read line
  do
    IS_NORMAL=0  
  done

  echo ${IS_NORMAL} 

上述程式碼,最後輸出 IS_NORMAL 值始終為 1,無法修改為 0,原因:

在 bash 指令碼中,管道符|會建立一個子 shell 來執行管道符右側的命令。在這個例子中,while read line 迴圈就在一個子 shell 中執行。因此,迴圈內部對變數 IS_NORMAL 的修改在子 shell 中發生,不會影響到主 shell 中的變數。

要解決這個問題,可以使用程序替代,將 while read line 迴圈作為主程序來執行。修改後程式碼如下:

  IS_NORMAL=1
  while read line
  do
    IS_NORMAL=0  
  done < <(df -BG) 

  echo ${IS_NORMAL} 

六、補充說明

1. du 和 df 的區別

dudf 都是 Linux 系統中的命令,用於檢查磁碟空間使用情況,但他們的使用方式和顯示的資訊有所不同。

(1) du 命令:du 是 "disk usage" 的縮寫,這個命令的主要作用是估算檔案或者目錄在磁碟中佔用的空間大小。它會遞迴地對目錄進行掃描,然後將每個子目錄的大小都計算出來。

   舉例:du -sh /home

這個命令會顯示 /home 目錄的總大小。-s 參數列示只顯示總計,-h 參數列示以易讀的格式顯示大小(例如 K,M,G)。

(2)df 命令:df 是 "disk filesystem" 的縮寫,這個命令的主要作用是顯示磁碟的使用情況。它會顯示所有已掛載的檔案系統的磁碟空間使用情況,包括總空間、已使用的空間、剩餘的空間以及使用的百分比。

   舉例:df -h

這個命令會以易讀的格式顯示所有已掛載的檔案系統的磁碟空間使用情況。-h 參數列示以易讀的格式顯示大小(例如 K,M,G)。

總的來說,dudf 的主要區別在於,du 是用來檢視檔案或目錄的大小,而 df 是用來檢視磁碟的使用情況。

相關文章