数据无价,服务器备份机制是服务器维护的重中之重!利用Dropbox的上传脚本+Monit监控实现服务器每周循环生成备份并上传到 Dropbox 网盘,通过 Shell 脚本实现出现备份失败及时通过邮件通知、自动清理旧的备份数据、禁止在黄金时段执行备份、禁止重复覆盖备份,确保服务器的宝贵数据万无一失!

环境安装

Monit 监控服务

安装没有什么技术难度,本文不再啰嗦,有包管理用包管理安装没包管理用源码编译安装,遇到困难自行Google。

RedHat / CentOS / Fedora

1
# yum install monit

Ubuntu / Debian / Linux Mint

1
$ apt-get install monit

Dropbox 上传脚本

直接使用 Andreafabrizi 写好的现成脚本 Dropbox-Uploader 稍作配置即可使用,配置教程下方提及。

下载 Dropbox 上传脚本

1
# GET 脚本到服务器
2
curl "https://raw.githubusercontent.com/andreafabrizi/Dropbox-Uploader/master/dropbox_uploader.sh" -o /back/dropbox_uploader.sh
3
# 赋予执行权限
4
chmod +x dropbox_uploader.sh

配置 Dropbox 上传脚本

访问 https://www.dropbox.com/developers/apps

创建 APP 程序 (点击Create app)
创建 Dropbox API

创建 API 密钥
创建 API 密钥

运行 dropbox_uploader.sh 按提示输入 Dropbox API 密钥

构建备份脚本

本脚本是基于 Monit 的监控原理来写的,所以最好配合 Monit 来使用(邮件报警功能是由 Monit 实现的)。由于我的服务器没有什么要用得上Mysql数据库的程序所以没写这方面的备份脚本,可直接备份Mysql的数据文件夹是一样的效果。

注意事项

  1. 临时文件夹:’BACK_DATA’ 变量的路径不能在要备份的文件夹内,最好就是设置在系统的 ‘tmp’临时文件夹内
  2. 备份文件夹:需要多少备份多少个目录就添加多少个数组,例:备份两个目录 ‘ folder[0]=”/…” folder[1]=”/…” ‘ 备份三个目录 ‘ folder[0]=”/…” folder[1]=”/…” folder[2]=”/…” ‘ 以此类推
  3. Dropbox的目录: ‘DROPBOX_DIR ‘要设置在子目录,这样设置有个好处就是多个服务器的备份不冲突
  4. 成功备份脚本返回 (0 ) 备份失败脚本返回(1)
1
#!/bin/bash
2
3
## 需要备份的文件夹
4
##########################
5
#需要备份多少个文件夹就添加几个数组(结尾不带/)
6
folder[0]="/data"
7
folder[1]="/etc"
8
9
## 参数设置
10
##########################
11
dropbox="/back/dropbox_uploader.sh"          #上传程序脚本位置
12
BACK_DATA="/tmp/dropbox_tmp"                 #临时文件夹(不要放在备份文件夹内)
13
DROPBOX_DIR=/$(hostname)                     #上传到Dropbox的目录 $(hostname)=当前主机名
14
tarconf="--exclude=*.log --exclude=*.pyc"    #tar打包压缩额外参数
15
olddata=2                                    #删除几周前的备份
16
uptime=0100                                  #只能在什么时间之前执行(输入纯数字)
17
upweek=1                                     #礼拜几执行(0代表星期天)
18
19
## 判断是否能执行
20
################################
21
if [ $(date +"%H%M") -gt $uptime ]; then    #判断是否在指定运行时间内
22
  echo "INFO: No running time" $uptime      #显示不在运行时间
23
  exit 0                                    #正常退出
24
fi
25
if [ $(date +"%w") -ne $upweek ]; then      #判断是否在指定运行周天内
26
  echo "INFO: No running week" $upweek      #显示不在运行时间
27
  exit 0                                    #正常退出
28
fi
29
result=$($dropbox -q search "_NO."$(date +"%Y")$(date +"%W").tar.gz)   #搜索云上本周备份文件
30
if [ -n "$result" ]; then                                              #判断云上是否有本周备份文件
31
  echo "INFO: Be backups $DROPBOX_DIR${result##*$DROPBOX_DIR}"         #显示云上已有本周的备份文件路径
32
  exit 0                                                               #正常退出
33
fi
34
35
## 数据上传
36
################################
37
## 建立临时文件夹
38
if [ ! -d "$BACK_DATA" ]; then
39
  sudo mkdir $BACK_DATA
40
fi
41
## 数据上传
42
sloop=${#folder[@]}                   #获取数组长度
43
let sloop-=1;                         #减1(数组从0开始)
44
for k in $( seq 0 $sloop ); do        #循环压缩上传
45
  tar zcf $BACK_DATA/${folder[$k]##*/}_$(date +"%Y%m%d")_NO.$(date +"%Y")$(date +"%W").tar.gz $tarconf -C ${folder[$k]%/*}/ ${folder[$k]##*/}    #压缩数据并生成时间与标识代码
46
  if [ $? != 0 ]; then                                                                                                                           #压缩失败
47
    echo "Error: Pack" ${folder[$k]##*/}_$(date +"%Y%m%d")_NO.$(date +"%Y")$(date +"%W").tar.gz "Error !"                                        #显示错误
48
    exit 1                                                                                                                                       #退出代码:1
49
  fi
50
  $dropbox -q upload $BACK_DATA/${folder[$k]##*/}_$(date +"%Y%m%d")_NO.$(date +"%Y")$(date +"%W").tar.gz $DROPBOX_DIR/$(date +%Y-%m-%d)/         #上传数据到当前日期文件夹
51
  if [ $? != 0 ]; then                                                                                                                           #上传失败
52
    echo "Error: UPload" ${folder[$k]##*/}_$(date +"%Y%m%d")_NO.$(date +"%Y")$(date +"%W").tar.gz "Error !"                                      #显示错误
53
    exit 1                                                                                                                                       #退出代码:1
54
  fi
55
done
56
echo "INFO: Upload data successfully" #成功上传数据
57
58
## 旧备份数据清理
59
################################
60
#提取星期\年份
61
wold=$(date +"%W")
62
yold=$(date +"%Y")
63
## 生成旧文件标识代码
64
let wold-=$olddata;         #减去olddata
65
if [ $wold -le 0 ]; then    #是负数执行
66
  let yold-=1               #年减一
67
  if [ $wold -lt 0 ]; then  #判断是否为负数
68
    let wold+=53            #与53相加
69
  else                      #不是负数
70
    wold=53                 #若不为负数则为最大值53
71
  fi
72
fi
73
## 搜索数据、删除数据
74
result=$($dropbox -q search "_NO.$yold$wold.tar.gz")       #根据旧文件标识代码搜索数据
75
if [ -n "$result" ]; then                                  #根据返回结果不为空执行
76
  result=${result##*$DROPBOX_DIR}                          #处理返回数据提取第一个$DROPBOX_DIR之前的内容
77
  $dropbox -q delete $DROPBOX_DIR/${result%/*}             #删除云数据(文件夹)
78
  echo "INFO: Deletes folder "$DROPBOX_DIR${result%/*}     #显示删除的文件夹
79
else                                                       #返回结果为空
80
  echo "INFO: NO OldCode "_NO.$yold$wold                   #云上没有指定文件标识的旧备份文件
81
fi
82
83
## 删除临时文件夹并退出
84
################################
85
rm -R $BACK_DATA
86
if [ $? != 0 ]; then
87
echo "Warning: $BACK_DATA Delete failed"
88
fi
89
exit 0

Monit 监控脚本

Monit 的强大配置都写完的话就跑题了,这里只写邮件服务器的配置和与本文相关的配置。

邮件服务器配置

1
## 每隔多少秒检测一次(第二行为程序启动后延时多少秒检测):
2
  set daemon 120
3
   with start delay 30
4
   
5
## 设置邮件通知服务器(smtp)
6
  set mailserver smtp.example.com port 443
7
      username "mail@example.com" 
8
      password "mailpassword"
9
      using TLSV1
10
      with timeout 30 seconds
11
      
12
## 设置邮件通知暂存地址
13
  set eventqueue
14
      basedir /var/lib/monit/events   # 储存地址
15
      slots 10                        # 最大储存数量
16
      
17
## 制定报警邮件的格式
18
set mail-format {
19
  from:    Monit <mail@example.com>
20
  subject: $HOST 服务器 $SERVICE 故障:$EVENT 
21
  message: 详细故障内容
22
23
               故障主机:  $HOST
24
               故障时间:  $DATE
25
               Monit 尝试动作:  $ACTION
26
                 
27
发生故障的条件
28
29
               $DESCRIPTION
30
31
Monit Server
32
}

备份脚本监控

1
#由于备份的时间较长所以设置为3600秒才超时
2
check program ServerBack with path /back/serverback timeout 3600 seconds
3
    #每 5(既 120*5 秒)个周期运行一次
4
    every 5 cycles
5
    #判断脚本退出码,若不为0则发送一封报警邮件
6
    if status != 0 then alert
7
    # 360(既 120*360 秒)个周期内只发送一封邮件给 hscbook@example.com
8
    alert hscbook@example.com with reminder on 360 cycles

END

遇到什么问题先 Google+Baidu 后再提问才是优秀的程序员!最后附上脚本原理的流程图 我就是想练练流程图的使用