最近公司要做一个数据备份,数据是用户产生的,基本上都是文件和图片。备份数据要打包成成 tar
包,所以设计如下方案:
bash shell
开发数据备份脚本dcp/backup
下tar
包,名字以年月日命名,如:2020-04-07.tar.gz
2020-04-07_all.tar.gz
天级:每天 00:00
备份昨天的产生的新数据
周级:每周周一 00:00
备份所有的全量数据
每天 00:00
删除 7 天之前的天级备份数据
每周周一 00:00
删除上周的周级备份数据
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命令格式及find命令详解
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