zl程序教程

您现在的位置是:首页 >  其他

当前栏目

一个合格的服务器自动备份案例,闭环备份机制出错邮件报警

2023-02-19 12:20:02 时间

数据无价,服务器备份机制是服务器维护的重中之重!利用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 上传脚本

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

创建 APP 程序 (点击Create app)

创建 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)
#!/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