多服務器統計用戶存儲總空間


背景:實驗室有5臺服務器。不同用戶在多個服務器上都可以有賬號,但是硬盤容量有限,如果一個人佔用大量存儲會導致其他人沒得用。作爲管理員,需要統計每個用戶在每一臺服務器上佔用的存儲空間,然後計算佔用的總空間,並記錄在一個文檔中方便查看。服務器的ID來自其局域網IP地址的最後一部分,分別爲102、106、112、120、146
注意:一下所有操作均使用root賬戶
整體流程

  1. 特定服務器(106服務器)製作密鑰然後發給其他各個服務器;
  2. 所有服務器每天3點半運行check_disk.sh,將本地的所有用戶的個人目錄大小記錄在XXX_check_disk.txt中,然後彙總到特定服務(106服務器)上;
  3. 特定服務器(106服務器)每天6點半運行count_disk_uasge_of_everyone.sh,根據user_list.txt統計每個用戶在每臺服務器上的個人目錄大小然後求和,記錄在disk_usage.txt
  4. 每臺服務器都使用crontab添加定時任務

接下來介紹其中的細節,請閱讀玩全文後再操作,如果有任何BUG歡迎留言:

腳本

check_disk.sh

這個文件需要部署到每一臺服務器上,放在/root下。統計本地服務器上所有用戶的存儲空間,然後統一發送到一個特定服務器上(我這裏選擇的是106服務器)。腳本內容如下,

#!/bin/bash
#獲取IP地址,用以識別服務器名稱
ip_address=$(/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:")
#IP地址後三個數字爲服務器代號
ID=${ip_address:0-3:3}
#文件名
file_name="$ID"_check_disk.txt
#添加時間和個人文件夾大小
echo `date +"%Y-%m-%d"` > $file_name
du -sm /home/* >> $file_name
if [ "$ID" != "106" ]
    then
        #統一發送到106服務器
        scp -i ~/.ssh/106_id_rsa $file_name [email protected]:/root/$file_name
    else 
        mv $file_name 106_check_disk.txt
fi

count_disk_uasge_of_everyone.sh

這個腳本用來統計用戶在每臺服務器上的存儲空間和在所有服務器上的總存儲空間。它只部署在特定服務器上,這裏就是上面說的106服務器,放在/root下。

#!/bin/bash
date_now=$(date +"%Y-%m-%d")
##### 創建文件disk_usage.txt,存儲每個人的文件佔有情況 #####
declare -i num=$(wc -l user_list.txt | awk '{print $1}')
#表頭,覆蓋舊的內容
echo "******************************************************" > disk_usage.txt
echo "********************  $date_now  ********************" >> disk_usage.txt
echo "******************************************************" >> disk_usage.txt
echo -e "姓名\t102(M)\t106(M)\t112(M)\t120(M)\t146(M)\t總和\t單位" >> disk_usage.txt
for (( i=2;i<=$num;i=i+1 ))
    do
        #每個人的使用情況先用服務器ID代替,方便後面查找到後替換
        echo -e "$(sed -n "$i"p user_list.txt | awk '{print $1}')\t_102\t_106\t_112\t_120\t_146\tsum\tunit" >> disk_usage.txt
    done

##### 檢索每臺服務器上的 #####
#日誌文件log.txt添加分割線
echo "********************  $date_now  ********************" >> log.txt
#統計每個服務器
for ID in 102 106 112 120 146
    do
    filename="$ID"_check_disk.txt
    #判斷文件是否存在
    if [ ! -e "$filename" ]; then
        echo -e "$date_now \t $filename not exists." >> log.txt
        continue
    fi
    #判斷文件時間是否一致
    if [ "$(grep -v "\home" "$filename")" != "$date_now" ]; then
        echo -e "$date_now \t $filename is old file." >> log.txt
        continue
    fi
    #獲取文件行數,即用戶數
    declare -i line_num=$(wc -l $filename | awk '{print $1}') #wc -l "$filename"輸出行號和文件名
    #echo "line_num is $line_num" 

    #處理每個用戶
    for (( i=2;i<=$line_num;i=i+1 ))
        do
        #單獨獲取用戶名和其使用的存儲容量
        username=$(sed -n "$i"p $filename | cut -f 3 -d "/" )
        disk_usage=$(sed -n "$i"p $filename | awk '{print $1}' )
        #echo "username is $username, disk_usage is $disk_usage"

        #判斷該用戶是否存在於user_list.txt中
        if [ "$(grep -w $username user_list.txt)" == "" ];then
            echo -e "$date_now \t $username in $ID not exits in user_list.txt." >> log.txt
            continue
        fi

        #獲取該用戶的中文名       
        fullname=$(grep -w $username user_list.txt | awk '{print $1}') #注意:需要全匹配!!!
        #echo "fullname is $fullname"

        #獲取該用戶在disk_usage.txt中的第幾行
        user_location=$(grep -n -w "$fullname" disk_usage.txt | cut -f 1 -d ':')
        #echo "user_location is $user_location"

        #將該用戶的存儲容量寫入disk_usage.txt的對應位置中
        sed -i "$user_location s/_$ID/$disk_usage/g" disk_usage.txt
        done

    done

##### 因爲有些用戶在有些服務器上沒有賬號,所以要將disk_usage.txt中沒有統計過的地方(即爲“_102”之類的地方)替換爲0 #####
for ID in 102 106 111 112 120 146
    do
    sed -i "s/_$ID/0/g" disk_usage.txt
    done
declare -i user_num=$(wc -l disk_usage.txt | awk '{print $1}')

##### 計算每個用戶的存儲空間總使用量 #####
declare -i user_num=$(wc -l disk_usage.txt | awk '{print $1}')
for (( i=5;i<=$user_num;i++ )) #前四行駛表頭
    do
    #計算總量
    declare -i usage_102=$(sed -n "$i"p disk_usage.txt | awk '{print $2}' )
    declare -i usage_106=$(sed -n "$i"p disk_usage.txt | awk '{print $3}' )
    declare -i usage_112=$(sed -n "$i"p disk_usage.txt | awk '{print $4}' )
    declare -i usage_120=$(sed -n "$i"p disk_usage.txt | awk '{print $5}' )
    declare -i usage_146=$(sed -n "$i"p disk_usage.txt | awk '{print $6}' )
    declare -i summary=$usage_102+$usage_106+$usage_112+$usage_120+$usage_146 #實驗證明也可以不加“$”
    
    #人性化顯示
    if [ $summary -gt 1024 ] #-gt表示大於
        then
        summary=summary/1024
        unit=G
    else
        unit=M
    fi

    #echo "this is $usage_102 $usage_106 $usage_112 $usage_120 $usage_146 $summary"
    
    #填入disk_usage.txt
    sed -i "$i s/sum/$summary/g" disk_usage.txt
    sed -i "$i s/unit/$unit/g" disk_usage.txt
    done

其他文件

user_list.txt

這個文件需手動準備,記錄了所有用戶的名字、在不同服務器上的用戶名和聯繫方法,放在特定服務器(即106服務器)。我是讓所有在服務器上有賬號的人填寫表格,示例如下:

姓名 102上賬號 106上賬號 112上賬號 120上賬號 146上賬號 手機 郵箱
小明 xm xm xm xiaoming 10086 [email protected]
小紅 xh xiaohong xiaohong xh 10086 [email protected]
小軍 xiaojun xiaojun 10086 [email protected]

我使用window的excel統計表格的,然後把內容直接粘貼到user_list.txt,再把user_list.txt複製到106服務器上的/root下面
注意:姓名不能重複,否則回報如下錯誤

sed: -e expression #1, char 3: unknown command: `
'

XXX_check_disk.txt

check_disk.sh自動生成,位於每個服務器的/root路徑下。記錄本地服務上每個用戶的個人文件夾的大小(以M爲單位),例如:

2020-02-27
312	/home/xm
31	/home/xh
40	/home/xiaojun

每次運行check_disk.sh都會覆蓋舊的XXX_check_disk.txt

log.txt

count_disk_uasge_of_everyone.sh自動生成,位於特定服務器(106服務器)的/root路徑下。記錄了count_disk_uasge_of_everyone.sh運行時的錯誤日誌,內容有:

  1. 日期
  2. 找不到XXX_check_disk.txt
  3. XXX_check_disk.txt裏記錄的時間跟現在的對不上,即沒有收到新版本
  4. XXX_check_disk.txt中的用戶不存在於user_list.txt

每次運行產生的錯誤日誌都會追加到log.txt

disk_usage.txt

count_disk_uasge_of_everyone.sh自動生成,位於特定服務器(106服務器)的/root路徑下。記錄了每個用戶在每臺服務上佔用存儲空間和它們的總和,如下:

******************************************************
********************  2020-02-27  ********************
******************************************************
姓名	102	106	112	120	146	總和
小明	312	0	0	0	33	345M
小紅	31	9	0	500	500	1G
小軍	40	0	22	0	0	62M

每次運行count_disk_uasge_of_everyone.sh都會覆蓋舊的disk_usage.txt

部署

公鑰

爲了使用scp傳輸文件時可以免密,這裏使用密鑰連接方式(其他的我搞不定)。在特定服務器(106服務器)上,執行命令ssh-keygen,選擇路徑和輸入密碼時都按回車直接跳過,然後執行

cat id_rsa.pub >> authorized_keys
#賦予文件權限
chmod 600 authorized_keys
chmod 700 ~/.ssh
cp id_rsa 106_id_rsa

然後把106_id_rsa放到其他每個服務器的/root/.ssh下面

定時任務

執行命令crontab -e,第一次運行的時候會讓選擇編輯器,如下
在這裏插入圖片描述
每個服務器都要在其中添加如下命令,讓check_disk.sh每天3點半運行一次:
在這裏插入圖片描述
特定服務器(106服務器)上還要再加上如下內容,讓count_disk_uasge_of_everyone.sh每天6點半運行一次

#每天統計每個用戶在所有服務器上佔用空間之和
30 6 * * * /root/count_disk_uasge_of_everyone.sh

具體格式參考附錄博客。

Linux crontab 命令

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章