重寫了伺服器備份的shell腳本,並加入了main函數
大家好,我是無能。
我重寫了之前寫的用於創建備份的shell腳本。
簡介
我之前寫過這個腳本,但重新審視時,發現沒有包含刪除舊的備份tar.gz檔案的程式碼,而且感覺會變得有點長,所以我將它整理到一個main函數中。
對於我這個懶人來說,盡可能地縮短程式碼非常重要,所以我嘗試重寫了它。
實際上,如果能透過參數指定備份目的地和來源,會更具通用性,而且在cron中編寫時也會更清晰易懂,所以我遲早會這麼做。
分解
#!/bin/bash
MOUNT_DIR="/your/mount/point"
SRC_DIR="/want/to/backup/dir"
BK_DIR="backupdir"
EXCLUDE_FILE="" # 指定排除檔案 --exclude=your/path
W_DIR=`echo $SRC_DIR | awk -F/ '{print $(NF)}'`
# 檢查掛載點,如果未掛載則掛載
check_mount() {
df | grep "$MOUNT_DIR" > /dev/null
if [ $? -ne 0 ]; then
break
else
mount $MOUNT_DIR || exit 1
fi
}
# 刪除舊的備份檔案
rm_old_backups() {
BK_COUNT=`ls -1 $MOUNT_DIR/$BK_DIR/*.tar.gz 2>/dev/null | wc -l`
if [ "$BK_COUNT" -ge 3 ]; then
ls -1t $MOUNT_DIR/$BK_DIR/*.tar.gz | tail -n +4 | while read file; do
rm -f "$file"
done
fi
}
# 創建備份
create_backup() {
rsync -av $EXCLUDE_FILE $SRC_DIR $MOUNT_DIR/$BK_DIR
tar cfz $MOUNT_DIR/$BK_DIR/"$W_DIR"_`date +"%Y%m%d"`.tar.gz -C $MOUNT_DIR/$BK_DIR $W_DIR
rm -rf $MOUNT_DIR/$BK_DIR/$W_DIR/*
}
main() {
check_mount # 檢查掛載,如果需要則掛載
mkdir -p $MOUNT_DIR/$BK_DIR # 創建備份目錄
rm_old_backups # 刪除舊的備份
create_backup # 創建新的備份
umount $MOUNT_DIR || exit 1 # 解除掛載
}
main
由於我預期會進行掛載/解除掛載操作,因此需要加入相關判斷。奇怪的是,當我嘗試使用mountpoint指令來判斷是否已掛載時,即使已經掛載,有時也會顯示「未掛載」,導致無法取得正確的回傳值。
因此,我突然想到,如果沒有掛載,它就不會出現在df的結果中。所以,透過grep df的標準輸出,並根據是否能grep到掛載點的回傳值來判斷,應該是相當可靠的。
原本我是用cp指令簡單地複製一次,然後再用tar打包,但因為我想指定「複製時排除的檔案」,聽說rsync可以用。這就是為什麼大家都在用rsync的原因吧。
之所以特意指定$W_DIR,是因為rsync會用到,所以需要先建立這個值。
而關鍵在於判斷並刪除舊的tar.gz檔案。透過ls來確認,就不會像find那樣貪婪地深入下層目錄,因此我認為這樣對磁碟I/O的負擔較小,也更安全,所以就這麼做了。
這樣一來,透過tail取得檔案名稱,就能明確決定允許保留多少個檔案,這不是挺好的嗎?
結尾
老實說,我感覺其實沒必要特地寫成main函數,但結果看起來確實更清晰了,所以就這樣吧。
那麼,下次再見了。