数据无价,服务器备份机制是服务器维护的重中之重!利用Dropbox的上传脚本+Monit监控实现服务器每周循环生成备份并上传到 Dropbox 网盘,通过 Shell 脚本实现出现备份失败及时通过邮件通知、自动清理旧的备份数据、禁止在黄金时段执行备份、禁止重复覆盖备份,确保服务器的宝贵数据万无一失!
环境安装
Monit 监控服务
安装没有什么技术难度,本文不再啰嗦,有包管理用包管理安装没包管理用源码编译安装,遇到困难自行Google。
RedHat / CentOS / Fedora
# yum install monit
Ubuntu / Debian / Linux Mint
$ apt-get install monit
Dropbox 上传脚本
直接使用 Andreafabrizi 写好的现成脚本 Dropbox-Uploader 稍作配置即可使用,配置教程下方提及。
下载 Dropbox 上传脚本
# GET 脚本到服务器 curl "<https://raw.githubusercontent.com/andreafabrizi/Dropbox-Uploader/master/dropbox_uploader.sh>" -o /back/dropbox_uploader.sh # 赋予执行权限 chmod +x dropbox_uploader.sh
配置 Dropbox 上传脚本
创建 APP 程序 (点击Create app)

创建 API 密钥

运行
dropbox_uploader.sh
按提示输入 Dropbox API 密钥构建备份脚本
本脚本是基于 Monit 的监控原理来写的,所以最好配合 Monit 来使用(邮件报警功能是由 Monit 实现的)。由于我的服务器没有什么要用得上Mysql数据库的程序所以没写这方面的备份脚本,可直接备份Mysql的数据文件夹是一样的效果。
注意事项
- 临时文件夹:'BACK_DATA' 变量的路径不能在要备份的文件夹内,最好就是设置在系统的 'tmp'临时文件夹内
- 备份文件夹:需要多少备份多少个目录就添加多少个数组,例:备份两个目录 ' folder[0]="/..." folder[1]="/..." ' 备份三个目录 ' folder[0]="/..." folder[1]="/..." folder[2]="/..." ' 以此类推
- Dropbox的目录: 'DROPBOX_DIR '要设置在子目录,这样设置有个好处就是多个服务器的备份不冲突
- 成功备份脚本返回 (0 ) 备份失败脚本返回(1)
#!/bin/bash ## 需要备份的文件夹 ########################## #需要备份多少个文件夹就添加几个数组(结尾不带/) folder[0]="/data" folder[1]="/etc" ## 参数设置 ########################## dropbox="/back/dropbox_uploader.sh" #上传程序脚本位置 BACK_DATA="/tmp/dropbox_tmp" #临时文件夹(不要放在备份文件夹内) DROPBOX_DIR=/$(hostname) #上传到Dropbox的目录 $(hostname)=当前主机名 tarconf="--exclude=*.log --exclude=*.pyc" #tar打包压缩额外参数 olddata=2 #删除几周前的备份 uptime=0100 #只能在什么时间之前执行(输入纯数字) upweek=1 #礼拜几执行(0代表星期天) ## 判断是否能执行 ################################ if [ $(date +"%H%M") -gt $uptime ]; then #判断是否在指定运行时间内 echo "INFO: No running time" $uptime #显示不在运行时间 exit 0 #正常退出 fi if [ $(date +"%w") -ne $upweek ]; then #判断是否在指定运行周天内 echo "INFO: No running week" $upweek #显示不在运行时间 exit 0 #正常退出 fi result=$($dropbox -q search "_NO."$(date +"%Y")$(date +"%W").tar.gz) #搜索云上本周备份文件 if [ -n "$result" ]; then #判断云上是否有本周备份文件 echo "INFO: Be backups $DROPBOX_DIR${result##*$DROPBOX_DIR}" #显示云上已有本周的备份文件路径 exit 0 #正常退出 fi ## 数据上传 ################################ ## 建立临时文件夹 if [ ! -d "$BACK_DATA" ]; then sudo mkdir $BACK_DATA fi ## 数据上传 sloop=${#folder[@]} #获取数组长度 let sloop-=1; #减1(数组从0开始) for k in $( seq 0 $sloop ); do #循环压缩上传 tar zcf $BACK_DATA/${folder[$k]##*/}_$(date +"%Y%m%d")_NO.$(date +"%Y")$(date +"%W").tar.gz $tarconf -C ${folder[$k]%/*}/ ${folder[$k]##*/} #压缩数据并生成时间与标识代码 if [ $? != 0 ]; then #压缩失败 echo "Error: Pack" ${folder[$k]##*/}_$(date +"%Y%m%d")_NO.$(date +"%Y")$(date +"%W").tar.gz "Error !" #显示错误 exit 1 #退出代码:1 fi $dropbox -q upload $BACK_DATA/${folder[$k]##*/}_$(date +"%Y%m%d")_NO.$(date +"%Y")$(date +"%W").tar.gz $DROPBOX_DIR/$(date +%Y-%m-%d)/ #上传数据到当前日期文件夹 if [ $? != 0 ]; then #上传失败 echo "Error: UPload" ${folder[$k]##*/}_$(date +"%Y%m%d")_NO.$(date +"%Y")$(date +"%W").tar.gz "Error !" #显示错误 exit 1 #退出代码:1 fi done echo "INFO: Upload data successfully" #成功上传数据 ## 旧备份数据清理 ################################ #提取星期\\年份 wold=$(date +"%W") yold=$(date +"%Y") ## 生成旧文件标识代码 let wold-=$olddata; #减去olddata if [ $wold -le 0 ]; then #是负数执行 let yold-=1 #年减一 if [ $wold -lt 0 ]; then #判断是否为负数 let wold+=53 #与53相加 else #不是负数 wold=53 #若不为负数则为最大值53 fi fi ## 搜索数据、删除数据 result=$($dropbox -q search "_NO.$yold$wold.tar.gz") #根据旧文件标识代码搜索数据 if [ -n "$result" ]; then #根据返回结果不为空执行 result=${result##*$DROPBOX_DIR} #处理返回数据提取第一个$DROPBOX_DIR之前的内容 $dropbox -q delete $DROPBOX_DIR/${result%/*} #删除云数据(文件夹) echo "INFO: Deletes folder "$DROPBOX_DIR${result%/*} #显示删除的文件夹 else #返回结果为空 echo "INFO: NO OldCode "_NO.$yold$wold #云上没有指定文件标识的旧备份文件 fi ## 删除临时文件夹并退出 ################################ rm -R $BACK_DATA if [ $? != 0 ]; then echo "Warning: $BACK_DATA Delete failed" fi exit 0
Monit 监控脚本
Monit 的强大配置都写完的话就跑题了,这里只写邮件服务器的配置和与本文相关的配置。
邮件服务器配置
## 每隔多少秒检测一次(第二行为程序启动后延时多少秒检测): set daemon 120 with start delay 30 ## 设置邮件通知服务器(smtp) set mailserver smtp.example.com port 443 username "mail@example.com" password "mailpassword" using TLSV1 with timeout 30 seconds ## 设置邮件通知暂存地址 set eventqueue basedir /var/lib/monit/events # 储存地址 slots 10 # 最大储存数量 ## 制定报警邮件的格式 set mail-format { from: Monit <mail@example.com> subject: $HOST 服务器 $SERVICE 故障:$EVENT message: 详细故障内容 故障主机: $HOST 故障时间: $DATE Monit 尝试动作: $ACTION 发生故障的条件 $DESCRIPTION Monit Server }
备份脚本监控
#由于备份的时间较长所以设置为3600秒才超时 check program ServerBack with path /back/serverback timeout 3600 seconds #每 5(既 120*5 秒)个周期运行一次 every 5 cycles #判断脚本退出码,若不为0则发送一封报警邮件 if status != 0 then alert # 360(既 120*360 秒)个周期内只发送一封邮件给 hscbook@example.com alert hscbook@example.com with reminder on 360 cycles