014 Linux 線上高頻使用以及面試高頻問題——如何查詢大檔案並安全的清除?

不甩鍋的碼農發表於2022-02-13

file

1 案例描述?

  1. 服務線上環境,會出現一些磁碟使用率過高而告警的情況,可能是某個日誌檔案過大,沒有及時清理回收,如何找到大目錄和大檔案?
  2. 如何安全的清理大檔案?
  3. 如何使佔用的磁碟空間快速釋放掉?

2 命令一(目錄統計排序最佳命令)

(這裡以當前目錄 ./ 為例,統計 top5)

【du -k --max-depth=1 ./ |sort -nr|head -n5】

[root@test-001 /]# du -k --max-depth=1 ./ |sort -nr|head -n5
137450839518	./
6785876	./data
2182577	./usr
1830341	./home
446856	./var

//du -k # 顯示目錄或檔案大小時,以 kB 為單位;
//du --max-depth=1 [目錄] # 只顯示指定目錄下第一層目錄(不含單個檔案)的大小;
//sort -nr # 以行為單位,根據數字大小從大到小排序;
//head -n5 # 顯示內容的開頭 5 行,這裡顯示就是 top5 內容;

3 命令二(最實用,目錄和檔案一起統計排序)

(這裡以當前目錄 ./ 為例,統計 top5)

(1)命令詳情和說明

【du -sk * ./ | sort -nr | head -n5 | awk -F'\t' '{if(1024 * 1024 * 1024 * 1024 > $1 && $1 >= 1024 * 1024 * 1024) {printf "%.2fT\t\t %s\n", $1/(1024 * 1024 * 1024), $2} else if(1024 * 1024 * 1024 > $1 && $1 >= 1024 * 1024) {printf "%.2fG\t\t %s\n", $1/(1024 * 1024), $2} else if (1024 * 1024 > $1 && $1 >= 1024) {printf "%.2fM\t\t %s\n", $1/1024, $2} else {printf "%sk\t\t %s\n", $1, $2}}' 】

[root@test-001 /]# du -sk * ./ | sort -nr | head -n5 | awk -F'\t' '{if(1024 * 1024 * 1024 * 1024 > $1 && $1 >= 1024 * 1024 * 1024) {printf "%.2fT\t\t %s\n", $1/(1024 * 1024 * 1024), $2} else if(1024 * 1024 * 1024 > $1 && $1 >= 1024 * 1024) {printf "%.2fG\t\t %s\n", $1/(1024 * 1024), $2} else if (1024 * 1024 > $1 && $1 >= 1024) {printf "%.2fM\t\t %s\n", $1/1024, $2} else {printf "%sk\t\t %s\n", $1, $2}}'
7.13G		 data
2.17G		 usr
1.75G		 home
447.04M		 var
408.50M		 run
//du -sk * # 顯示當前目錄下每個資料夾和檔案的大小以KB為單位(最常用),s表示彙總,k是以KB為統計單位;
//./ #當前目錄下
//sort -nr # 以行為單位,根據數字大小從大到小排序;
//awk -F'\t'# 以水平製表符進行分割,後面的程式就是進行換算單位,格式化輸出成易懂的形式;

(2)du、head、sort、awk 詳細說明參考已有文章附錄

(3)Linux 中 printf 命令使用參考

// Linux 中 printf 命令使用參考
// https://www.linuxprobe.com/linux-printf-example.html

'{
    if(1024 * 1024 * 1024 * 1024 > $1 && $1 >= 1024 * 1024 * 1024) 
    {
        printf "%.2fT\t\t %s\n", $1/(1024 * 1024 * 1024), $2
    } 
    else if(1024 * 1024 * 1024 > $1 && $1 >= 1024 * 1024) 
    {
        printf "%.2fG\t\t %s\n", $1/(1024 * 1024), $2
    } 
    else if (1024 * 1024 > $1 && $1 >= 1024) 
    {
        printf "%.2fM\t\t %s\n", $1/1024, $2
    } 
    else 
    {
        printf "%sk\t\t %s\n", $1, $2
    }
}'

4 如何安全使用 rm 命令刪除檔案?

(1)rm 命令有哪些坑?

  • rm -rf / # 這個命令絕逼不能操作?,刪除根目錄下的檔案,就是系統中的所有檔案都要被刪除。如果是線上服務機器操作了,那就悲劇了!誤操作了怎麼辦?趕快ctrl+c、ctrl+z 能保住多少是多少吧。
  • rm -rf / home/apps/logs/ # 這也是個天坑命令!目的是刪除日誌文。結果書寫時“多了一個空格”的 bug,看懂了麼?這就變成了 [rm -rf /] !
  • 埋藏隱患的日誌清理 shell 指令碼!指令碼關鍵內容如下。
cd ${log_path}
rm -rf *

目的是:進入到日誌目錄,然後把日誌都刪除。隱患:當目錄不存在時,悲劇就發生了!

(2)如何安全使用 rm 命令?

  • 在生產環境把 [rm -rf] 命令替換為 [mv],再寫個指令碼程式定期清理,模擬回收站的功能。
  • 把日誌清理 shell 指令碼,改用邏輯與 && 進行連線。
cd ${log_path}
rm -rf *

改用邏輯與 && 進行連線,合併成一句,前半句邏輯失敗,後半句命令不執行:
 ```shell
cd ${log_path} && rm -rf *

完整的日誌清理 shell 指令碼如下:
 ```shell
#!/bin/bash
base_home="/home/apps"
log_path=${base_home}/logs
cd ${log_path} && rm -rf *

5 磁碟使用率報警,卻查不到具體的大檔案?

(1)問題情景

  • 1 磁碟使用率監控報警,進入機器可以 (df -h) 命令看到磁碟使用率確實超過了報警閥值。

  • 2 使用命令檢視大目錄,並進入到目錄下 【du -sk * ./ | sort -nr | head -n5 | awk -F'\t' '{if(1024 * 1024 * 1024 * 1024 > $1 && $1 >= 1024 * 1024 * 1024) {printf "%.2fT\t\t %s\n", $1/(1024 * 1024 * 1024), $2} else if(1024 * 1024 * 1024 > $1 && $1 >= 1024 * 1024) {printf "%.2fG\t\t %s\n", $1/(1024 * 1024), $2} else if (1024 * 1024 > $1 && $1 >= 1024) {printf "%.2fM\t\t %s\n", $1/1024, $2} else {printf "%sk\t\t %s\n", $1, $2}}' 】

  • 3 依然沒找到大檔案,該怎麼辦呢?

(2)排查思路

  • 1 思考:是不是有檔案已經被刪除了,但程式還在佔用該檔案,程式未結束,空間未釋放?
  • 2 使用「lsof |grep -i deleted」命令檢視,能檢視到已刪除,空間沒有釋放的檔案,包含檔案大小,程式和服務名等資訊。

file

lsof(List Open Files) 用於檢視程式開啟的檔案,開啟檔案的程式,程式開啟的埠(TCP、UDP),找回/恢復刪除的檔案。是十分方便的系統監視工具,因為 lsof 命令需要訪問核心記憶體和各種檔案,所以需要root 使用者許可權執行。

(3)佔用磁碟空間釋放

重啟下程式所指的服務,佔用的磁碟空間即可釋放掉。線上生產操作一定要謹慎,不要直接 kill 掉程式,評估看是否有程式服務自身的重啟名命令,以及評估服務是否可以重啟。

(4)備註附錄

  • 1 當一個檔案正在被一個程式使用時,使用者刪除此檔案,檔案只會從目錄結構中刪除,但並沒有從磁碟刪除。
  • 2 當使用這個檔案的程式結束後,檔案才會真正的從磁碟刪除,釋放佔有的空間。Linux 開啟一個檔案的時候,核心會為每個程式在 /proc/ 『/proc/{nnnn}/fd/資料夾({nnnn} 為 pid)』建立一個以其 pid 為名的資料夾用來儲存程式的相關資訊,而其子資料夾 fd 儲存的是該程式開啟的全部檔案的 fd(fd:file descriptor)。
  • 3 Ctrl + C 和 Ctrl + Z都是中斷命令。Ctrl + C 是強制中斷程式的執行,程式已經終止;Ctrl + Z 是將任務中止(暫停的意思),他仍然在程式中他只是維持掛起的狀態。

6 生產環境常用的安全清理大檔案命令

  1. 生產環境安全清理大檔案的訴求是什麼?既要不影響服務的正常執行,又要讓磁碟佔用的空間快速釋放掉(讓檔案消失掉不是我們的目的,我們的目的是快速釋放掉佔用的磁碟空間)。
  2. 不要使用 「rm -rf xxx.log」;常用 「echo "" > xxx.log」。
  3. 這裡假設 xxx.log 為大檔案,如這個 xxx.log 有幾十個 GB,「echo "" > xxx.log」是用一個 "" 內容覆蓋原檔案內容,使磁碟空間得到瞬間釋放!

7 小結

  1. 總結了查詢大目錄以及大檔案的常用組合命令(涉及到 du、head、sort、awk 等命令);
  2. 以及如何安全使用 rm 命令;
  3. 還有在磁碟使用率報警,卻查不到具體的大檔案的情況如何排查;
  4. 最後還提到了常用的 echo 命令對原檔案進行覆蓋以達到使磁碟空間佔用得到瞬間釋放。

「不甩鍋的碼農」原創,轉載請註明來源,未經授權禁止商業用途!同名 GZH 請關注!

相關文章