#!/bin/bash
# Author: Hebin Wan
# Description:对 MongoDB 的 Oplog 进行增量备份,脚本会备份 Oplog 中最近65分钟之内的增量数据。
# Note: 需要注意一个变量: diffTime
#       第一次定义这个变量的时候,是为了定义备份的时长,从此刻到之前 65 * 60ms 之前的时间,也就是备份从现在到之前 1小时5分这段时间的增量;
#       第二次定义这个变量的时候,是为了避免数据增长过快,覆盖了还未备份的数据的,比较的依据是 rs.printReplicationInfo(); 的 oplog first event time 时间。
#       这两个定义的时间可灵活调整。

DATE1=`date +%Y-%m-%d_%H-%M`
DATE2=`date "+%H:%M:%S %F"`
#HOST_IP=`ip a s eth0 | awk -F'[ /]*' 'NR==3{print $3}'`

Back_Dir='/data/backup/mongodb-backup/incremental'
Back_File="mongodb-prod_incremental_$DATE1"
Back_Gz_File="${Back_File}.tar.gz"
Back_Log="$Back_Dir/logs"
logfilename="incremental-$(date +"%Y%m%d")"

Mongo_User='backupuser'
Mongo_Pass='backuppass'
Mongo_Host='10.0.1.41:27017,10.0.1.42:27017,10.0.1.43:27017'

Connect_Command="/usr/local/bin/mongo 10.0.1.42:27017 -u $Mongo_User -p $Mongo_Pass --authenticationDatabase admin"

[ -d $Back_Dir ] || mkdir -p $Back_Dir
[ -d $Back_Log ] || mkdir -p $Back_Log

echo -e "\n+++++++++++++++++++++++++++++++++++++ Mongodb FULL BACKUP BEGIN +++++++++++++++++++++++++++++++++++++\n"
echo "===MongoDB 基于 Oplog 的增量备份开始,开始时间为: " $(date +"%Y-%m-%d %H:%M:%S")

paramBakEndDate=$(date +%s)
echo -e "\n===本次备份时间参数中的结束时间为(时间戳): $paramBakEndDate (`date -d @$paramBakEndDate "+%Y-%m-%d %H:%M:%S"`)"

diffTime=$(expr 65 \* 60)
echo "===备份设置的间隔时间为(s): " $diffTime

paramBakStartDate=$(expr $paramBakEndDate - $diffTime)
echo "===本次备份时间参数中的开始时间为(时间戳): $paramBakStartDate (`date -d @$paramBakStartDate "+%Y-%m-%d %H:%M:%S"`)"

#opmes=$(/bin/echo "rs.printReplicationInfo()" | $Connect_Command --quiet)
$Connect_Command --quiet --eval "rs.printReplicationInfo()" >/tmp/opdoctime.tmplog
#echo $opmes > /tmp/opdoctime.tmplog
opbktmplogfile='/tmp/opdoctime.tmplog'
#opstartmes=$(grep "oplog first event time" $opbktmplogfile | awk -F 'CST' '{print $1}' | awk -F 'oplog first event time: ' '{print $2}' | awk -F ' GMT' '{print $1}')
opstartmes=$(grep -Po '(?<=oplog first event time:).*(?=GMT+)' $opbktmplogfile)
oplogRecordFirst=$(date -d "$opstartmes"  +%s)
echo "===Oplog集合记录的开始时间为(时间戳): $oplogRecordFirst (`date -d @$oplogRecordFirst "+%Y-%m-%d %H:%M:%S"`)"
if [ $oplogRecordFirst -le $paramBakStartDate ]; then
    echo "Message Info --检查设置备份时间合理。备份参数的开始时间在 Oplog 记录的时间范围内。"
else
    echo "Fatal Error --检查设置的备份时间不合理合理。备份参数的开始时间不在 Oplog 记录的时间范围内。请调整 Oplog Size 或调整备份频率。本次备份可以持续进行,但还原时数据完整性丢失。"
fi
# 执行增量备份操作 
/usr/local/bin/mongodump -h $Mongo_Host -u $Mongo_User -p $Mongo_Pass --authenticationDatabase admin -d local -c oplog.rs --query '{ts:{$gte:Timestamp('$paramBakStartDate',1),$lte:Timestamp('$paramBakEndDate',9999)}}' -o $Back_Dir/$Back_File --readPreference=primaryPreferred

######################################## Oplog 检验 ########################################
diffTime=$(expr 61 \* 60)
paramAfterBakRequestStartDate=$(expr $paramBakEndDate - $diffTime)
echo "===为保证备份的连续性,本次备份后,Oplog 中的开始时间需小于(时间戳): $paramAfterBakRequestStartDate (`date -d @$paramAfterBakRequestStartDate "+%Y-%m-%d %H:%M:%S"`)"

#opmes=$(/bin/echo "rs.printReplicationInfo()" | $Connect_Command --quiet)
$Connect_Command --quiet --eval "rs.printReplicationInfo()" >/tmp/opdoctime.tmplog
#echo $opmes > /tmp/opdoctime.tmplog
opbktmplogfile=/tmp/opdoctime.tmplog
#opstartmes=$(grep "oplog first event time" $opbktmplogfile | awk -F 'CST' '{print $1}' | awk -F 'oplog first event time: ' '{print $2}' | awk -F ' GMT' '{print $1}')
opstartmes=$(grep -Po '(?<=oplog first event time:).*(?=GMT+)' $opbktmplogfile)
oplogRecordFirst=$(date -d "$opstartmes"  +%s)
echo "===执行备份后,Oplog 集合记录的开始时间为(时间戳): $oplogRecordFirst (`date -d @$oplogRecordFirst "+%Y-%m-%d %H:%M:%S"`)"

if [ $oplogRecordFirst -le $paramAfterBakRequestStartDate ]; then
    echo "Message Info --备份后,检查 Oplog 集合中数据的开始时间,即集合中最早的一笔数据,时间不小于61分钟的时间(即参数 paramAfterBakRequestStartDate)。这样可以保证每个增量备份含有最近一个小时的全部op操作,满足文件的持续完整性,逐个还原无丢失数据风险。"
else
    echo "Fatal Error --备份后,检查 Oplog 集合的涵盖的时间范围过小(小于61min)。设置的备份时间不合理合理,备份后的文件不能完全涵盖最近60分钟的数据。请调整 Oplog Size 或调整备份频率。本次备份可以持续进行,但还原时数据完整性丢失。"
fi

# 检查备份文件是否生成
if [ -d "$Back_Dir/$Back_File" ]; then
    echo "Message Info --检查此次备份文件已经产生文件信息为:" $Back_Dir/$Back_File >> $Back_Log/${logfilename}.log
else
    echo "Fatal Error --备份过程已执行,但是未检测到备份产生的文件,请检查!" >> $Back_Log/${logfilename}.log
fi

echo -e "\n===MongoDB 基于Oplog的增量备份结束,结束时间为: " $(date -d today +"%Y-%m-%d %H:%M:%S")
echo -e "\n+++++++++++++++++++++++++++++++++++++ MongoDB FULL BACKUP END +++++++++++++++++++++++++++++++++++++\n"

# 对增量备份文件打包压缩
cd $Back_Dir
tar zcf $Back_Gz_File $Back_File
rm -rf $Back_File
cd /root/

# 保留近7天的增量日志
#keepbaktime=$(date -d '-4 days' "+%Y-%m-%d")
#ls -d1 /data/backup/mongodb-backup/incremental/*${keepbaktime}* &>/dev/null
#if [ $? -eq 0 ]; then
#    ls -d1 /data/backup/mongodb-backup/incremental/*${keepbaktime}* > /tmp/mongodb_inc_expire.txt
#    for expire_file in `cat /tmp/mongodb_inc_expire.txt`
#    do
#        rm -rf $expire_file
#        echo "Message Info -- $expire_file 删除完毕" >> $Back_Log/${logfilename}.log
#    done
#fi