文章目錄
背景:實驗室有5臺服務器。不同用戶在多個服務器上都可以有賬號,但是硬盤容量有限,如果一個人佔用大量存儲會導致其他人沒得用。作爲管理員,需要統計每個用戶在每一臺服務器上佔用的存儲空間,然後計算佔用的總空間,並記錄在一個文檔中方便查看。服務器的ID來自其局域網IP地址的最後一部分,分別爲102、106、112、120、146
注意:一下所有操作均使用root賬戶
整體流程:
- 特定服務器(106服務器)製作密鑰然後發給其他各個服務器;
- 所有服務器每天3點半運行
check_disk.sh
,將本地的所有用戶的個人目錄大小記錄在XXX_check_disk.txt
中,然後彙總到特定服務(106服務器)上; - 特定服務器(106服務器)每天6點半運行
count_disk_uasge_of_everyone.sh
,根據user_list.txt
統計每個用戶在每臺服務器上的個人目錄大小然後求和,記錄在disk_usage.txt
上 - 每臺服務器都使用
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
運行時的錯誤日誌,內容有:
- 日期
- 找不到
XXX_check_disk.txt
XXX_check_disk.txt
裏記錄的時間跟現在的對不上,即沒有收到新版本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
具體格式參考附錄博客。