最近公司要做一個數據備份,數據是用戶產生的,基本上都是文件和圖片。備份數據要打包成成 tar
包,所以設計如下方案:
《用戶數據備份方案》
1. 採用 bash shell
開發數據備份腳本
2. 數據備份目錄新建在 dcp/backup
下
3. 所有需要備份的文件打包爲 tar
包,名字以年月日命名,如:2020-04-07.tar.gz
2020-04-07_all.tar.gz
4. 備份規則:
-
天級:每天
00:00
備份昨天的產生的新數據 -
周級:每週週一
00:00
備份所有的全量數據
5. 刪除規則:
-
每天
00:00
刪除 7 天之前的天級備份數據 -
每週週一
00:00
刪除上週的周級備份數據
6. 定時執行:
- 使用
crontab
執行定時任務
方案設計好以後就可以進行開發了。但是在開發的過程中遇到了不少小坑。
坑一:date
命令
由於我使用 Mac 進行開發的,所以在做時間處理的時候遇到了一些坑。 date
在進行時間加減的時候用的參數是 -d
,但是在 Mac 下就報錯了。這是因爲在 Mac 下參數變成 -v
參考資料:
https://blog.csdn.net/weixin_37696997
https://www.cnblogs.com/alsodzy/p/8403870.html
https://blog.csdn.net/guddqs/article/details/80745464
爲了兼容 Mac 和 Linux 發行版,我們需要判斷當前系統是什麼
#!/bin/bash
if [[ `uname -a` =~ "Darwin" ]]
then
echo "Mac"
elif [[ `uname -a` =~ "centos" ]]
then
echo "Centos"
elif [[ `uname -a` =~ "ubuntu" ]]
then
echo "Ubuntu"
else
echo "Other"
fi
~
是判斷右側正則表達式是否匹配,匹配輸出 1 不匹配輸出 0
坑二: tar
包絕對路徑
tar 打包是在相對路徑下進行的
tar cvzf 2020_04-08_all.tar.gz files/
但是我們在寫腳本爲了路徑正確,經常要用到絕對路徑,如果直接使用有時會報錯的,需要加上 P
參數,記得要放在 f
參數之前
tar cvzPf 2020_04-08_all.tar.gz /data/dcp/www/files/
坑三: tar
指定解壓後的目錄
如果直接用絕對路徑打包,解壓後包裏面的目錄是從根目錄開始的,如果想指定文件的上級目錄就需要加上 -C
參數來指定目錄,然後指定解壓後的目錄是 files
tar cvzPf 2020_04-08_all.tar.gz -C /data/dcp/www files
坑四:find
和 tar
配合使用
在打包的時候,有時候並不是所有的數據都要,這時候就需要過濾一部分數據進行打包,過濾查找就用 find
命令
find
和 tar
配合使用有很多方式,具體參考下面的鏈接
How to find and tar files into a tar ball
這裏我們使用最常見的管道命令
find /data/dcp/www/files -mtime 0 | xargs tar cvzf 2020_04-08.tar.gz
或者使用 -exec
命令
find /data/dcp/www/files -mtime 0 -exec tar cvzf 2020_04-08.tar.gz {} +
坑四:數據冗餘
上述命令看似沒有問題,但是在打包的時候回打包成多餘的冗餘數據,這是爲什麼呢?
原因是目錄也有時間信息,如果要忽略目錄只要文件,那麼只需要加上 -type f
參數就好
find /data/dcp/www/files -type f -mtime 0 | xargs tar cvzf 2020_04-08.tar.gz
坑五:find
和 tar
指定解壓後的目錄
使用 find
命令,打包需要管道,但是命令格式就會發生變化,爲了指定目錄,我們需要變通,換一種方式
cd /data/dcp/www
find files -mtime 0 | xargs tar cvzf 2020_04-08.tar.gz
這樣就可以指定 find
和 tar
解壓後的目錄
最後放出用戶數據備份的源碼:
#!/bin/bash
# today
dt=`date +"%Y-%m-%d"`
# src and dest file path
src="/data/dcp/www"
dest="/data/dcp/backup"
day() {
find ${dest} -type f -name ${last_week}.tar.gz | xargs rm -rf
cd $src
find files -type f -mtime 0 | xargs tar cvzf ${dest}/${yesterday}.tar.gz
}
week() {
find ${dest} -type f -name ${last_week}_all.tar.gz | xargs rm -rf
cd $src
tar cvzf ${dest}/${dt}_all.tar.gz files/
}
# Judge Mac or Linux
if [[ `uname -a` =~ "Darwin" ]]
then
yesterday=`date -v -1d +"%Y-%m-%d"`
last_week=`date -v -1w +"%Y-%m-%d"`
else
yesterday=`date -d '-1 day' +%Y-%m-%d`
last_week=`date -d '-1 week' +%Y-%m-%d`
fi
# day or week type
if [ "$1" = "day" ]
then
day
elif [ "$1" = "week" ]
then
week
else
echo "--------- *Please input task type* ----------"
echo "bash $0 day [OR] bash $0 week"
fi
最後,在 crontab
中添加定時任務
0 0 * * * bash /data/dcp/script/dcp_user_data_backup.sh day
0 0 * * 1 bash /data/dcp/script/dcp_user_data_backup.sh week