#!/bin/bash
# Author:寂寞行走Penguin
# 颜色
ColorStart="\033[" #${ColorStart}#
ColorEnd="\033[0m" #${ColorEnd}#
ColorBlack="\033[30;1m" #黑色# #${ColorBlack}#
ColorRed="\033[31;1m" #红色# #${ColorRed}#
ColorGreen="\033[32;1m" #绿色# #${ColorGreen}#
ColorYellow="\033[33;1m" #黄色# #${ColorYellow}#
ColorBlue="\033[34;1m" #蓝色# #${ColorBlue}#
ColorPink="\033[35;1m" #粉色# #${ColorPink}#
ColorCyan="\033[36;1m" #青色# #${ColorCyan}#
ColorWhite="\033[37;1m" #白色# #${ColorWhite}#
# 时间相关参数
Date=$(date +%F)
Time=$(date +%F_%T)
# 本机IP(任选一种方法即可)
#Ip=$(hostname -i)
Ip=$(hostname -I | awk '{print $2}')
#Ip=$(ip a | grep "scope global" | sed -n 2p | awk '{print $2 | "xargs dirname"}')
DevNull=">/dev/null 2>&1"
# 备份命令
XbkCmd=$(which innobackupex)
# 配置文件
# 如果一台服务器上起了多个mysql实例,那么可以按照端口号或者实例的具体用途来定义多个my.cnf的参数,视实际情况决定即可
MyCnf="/etc/my.cnf"
# mysql备份用户
XbkUser='xbk'
# mysql用户mima
XbkPass='xbkpw'
# 谁的备份
# 练习的时候不确定性高,用传参的方式来定义比较方便;用于业务线上的时候必然可以固定下来,直接写死即可
Domain=$1
# 全备和增备数据存放位置
XbkDir="/data/xtrabackup/${Domain}/${Ip}/${Date}"
# 全备数据存放位置
XbkAllDir=${XbkDir}/all
# tar包存放位置
SqlTarDir="/data/xtrabackup/RsyncPackage/${Domain}/${Ip}"
# 日志相关参数
# log文件存放位置
XbkLogDir="/data/logs/xtrabackup/"
# log文件名
LogFile="xtrabackup_${Domain}_${Ip}_${Date}.log"
function REPORT
{
echo -e "${ColorStart}${ColorYellow}[${Time}]${ColorEnd} $1"
}
# Extension of REPORT,提示信息
function REPORT_INFO
{
REPORT "[INFO] ${ColorStart}${ColorGreen}$1${ColorEnd}"
}
# Extension of REPORT,报错 & 退出
function REPORT_WARN
{
REPORT "[WARNING] ${ColorStart}${ColorRed}$1${ColorEnd}" && exit 3
}
# 检查存放日志的目录及文件是否存在,若不存在则创建
# This function is used to check if the XbkLogDir and LogFile already exist.
function CHECK_LOG_DIR_FILE
{
REPORT_INFO "Check XbkLogDir and LogFile."
if [ ! -d ${XbkLogDir} ]
then
REPORT_INFO "XbkLogDir doesn't exist, create XbkLogDir and LogFile."
mkdir -p ${XbkLogDir} && touch ${XbkLogDir}${LogFile}
elif [[ -d ${XbkLogDir} && ! -f ${XbkLogDir}${LogFile} ]]
then
REPORT_INFO "XbkLogDir exists, LogFile doesn't exist, create LogFile only."
touch ${XbkLogDir}${LogFile}
else
REPORT_INFO "XbkLogDir and LogFile all exist, anything needn't to do."
fi
[[ ! -d ${XbkLogDir} || ! -f ${XbkLogDir}${LogFile} ]] && REPORT_WARN "Something was wrong when 'CHECK_LOG_DIR_FILE', please check."
sleep 1
}
# 检查存放压缩数据的目录是否存在,若不存在则创建
# This function is used to check if the SqlTarDir already exists.
function CHECK_SQL_TAR_DIR
{
REPORT_INFO "Check Sql_Tar_Dir."
#[ ! -d ${SqlTarDir} ] && mkdir -p ${SqlTarDir}
#[ -d ${SqlTarDir} ] || REPORT_WARN "Something was wrong when create ${SqlTarDir}, please check."
# if [ -d ${SqlTarDir} ]
# then
# REPORT_INFO "SqlTarDir exists, go on."
# else
# mkdir -p ${SqlTarDir} && [ $? -ne 0 ] && REPORT_INFO "SqlTarDir exists, go on." || REPORT_WARN "Something was wrong when create ${SqlTarDir}, please check."
# fi
if [ -d ${SqlTarDir} ]
then
REPORT_INFO "SqlTarDir exists, go on."
else
mkdir -p ${SqlTarDir}
fi
[ -d ${SqlTarDir} ] && REPORT_INFO "SqlTarDir exists, go on." || REPORT_WARN "Something was wrong when 'CHECK_SQL_TAR_DIR', please check."
}
# 检查innobackupex命令是否存在,若不存在则报错并退出
# This function is used to check if the innobackupex commond already exists.
function CHECK_CMD
{
REPORT_INFO "Check commond innobackupex."
#${XbkCmd} -v 2>/dev/null 1>/dev/null
${XbkCmd} -v ${DevNull}
if [ $? -ne 0 ]
then
REPORT_WARN "Commond innobackupex doesn't exist, please check."
else
REPORT_INFO "Commond innobackupex exists, go on."
fi
sleep 1
}
# 传输tar包到存储服务上的函数,需要提前在存储服务器上部署好rsync服务的守护进程模式
# This function is used to rsync data_sql to storage server.
function RSYNC
{
RsyncFile=$1
RsyncPath=$2
RsyncServer="存储服务器的IP或域名"
SleepTime=`expr $(/usr/bin/hexdump -n4 -e\"%u\" /dev/urandom) % 900`
sleep ${SleepTime}
rsync -avr ${RsyncFile} ${RsyncServer}::${RsyncPath}/${Domain}
# 检查check
if [[ $? -ne 0 ]]
then
REPORT_WARN "Rsync Failed, please check."
else
REPORT_INFO "Rsync Success, congratulation."
fi
}
# 全备的函数
# This function is used for backup all data.
function BACKUP_ALL
{
cat /dev/null > ${XbkLogDir}${LogFile}
# 因为是按天创建目录,所以存放备份数据的目录一定是不存在的,故无需检查直接创建即可。
# create directory for xtrabackup.
REPORT_INFO "Create directory for xtrabackup."
mkdir -p ${XbkDir}
sleep 3
# 执行全备
# start full backup
REPORT_INFO "Start to back up ${Domain}/${Ip} all data."
${XbkCmd} --defaults-file=${MyCnf} --user=${XbkUser} --password=${XbkPass} --no-timestamp ${XbkAllDir} ${DevNull}
sleep 5
# 检查check
if [ $? -ne 0 ]
then
REPORT_WARN "Failed to back up ${Domain}/${Ip} all data, please check."
else
REPORT_INFO "Successfully backed up ${Domain}/${Ip} all data."
fi
# 压缩数据,打tar包
REPORT_INFO "Start to package ${Domain}/${Ip} all backup data."
cd ${XbkAllDir}
if [ `pwd` = ${XbkAllDir} ]
then
tar -zcf ${SqlTarDir}/${Domain}_xbk_all_${Date}.sql.tar.gz *
else
REPORT_WARN "Something was wrong when TAR ${Domain}/${Ip} all backup data, please check."
fi
sleep 3
# 检查check
if [ $? -ne 0 ]
then
REPORT_WARN "Failed to package ${Domain}/${Ip} all backup data, please check."
else
REPORT_INFO "Successfully ${Domain}/${Ip} packageed all backup data."
fi
# 传输tar包到存储服务上,调用RSYNC函数
# 需要2个参数,第1个参数是要传输的数据,第2个参数是想要使用的存储服务器上配置的rsync守护进程模式的模块名字
REPORT_INFO "Start to sync ${Domain}/${Ip} all backup data."
RSYNC ${SqlTarDir}/../ "backup_data"
sleep 3
# 传输完毕后删除tar包,释放本机磁盘空间
REPORT_INFO "End rsync, delete ${SqlTarDir}/${Domain}_xbk_all_${Date}.sql.tar.gz"
rm -f ${SqlTarDir}/${Domain}_xbk_all_${Date}.sql.tar.gz
sleep 3
}
# 增备的函数
# This function is used for backup incremental data.
function BACKUP_INC
{
cd ${XbkDir}
local LastPath=$(ls -drt inc* all | tail -1)
#local LastPath=$(ls -drt * | tail -1)
if [[ ${LastPath} == "all" ]] 2>/dev/null 1>/dev/null
then
local num=1
else
local num=$(expr $(echo ${LastPath} | grep -o "[0-9][0-9]*$") + 1 )
fi
# 执行增备
# start inc backup
REPORT_INFO "Start to back up ${Domain}/${Ip} inc_$num data."
${XbkCmd} --defaults-file=${MyCnf} --user=${XbkUser} --password=${XbkPass} --no-timestamp --incremental --incremental-basedir=${XbkAllDir} ${XbkDir}/inc_$num ${DevNull}
sleep 5
# 检查check
if [ $? -ne 0 ]
then
REPORT_WARN "Failed to back up ${Domain}/${Ip} inc_$num data, please check."
else
REPORT_INFO "Successfully backed up ${Domain}/${Ip} inc_$num data."
fi
# 压缩数据,打tar包
REPORT_INFO "Start to package ${Domain}/${Ip} inc_$num backup data."
cd ${XbkDir}/inc_$num
if [ `pwd` = ${XbkDir}/inc_$num ]
then
tar -zhcf ${SqlTarDir}/${Domain}_xbk_inc_${num}_${Date}.sql.tar.gz *
else
REPORT_WARN "Something was wrong when TAR ${Domain}/${Ip} inc_$num backup data, please check."
fi
sleep 3
# 检查check
if [ $? -ne 0 ]
then
REPORT_WARN "Failed to package ${Domain}/${Ip} inc_$num backup data, please check."
else
REPORT_INFO "Successfully packaged ${Domain}/${Ip} inc_$num backup data."
fi
# 传输tar包到存储服务上,调用RSYNC函数
# 需要2个参数,第1个参数是要传输的数据,第2个参数是想要使用的存储服务器上配置的rsync守护进程模式的模块名字
REPORT_INFO "Start to sync ${Domain}/${Ip} inc_$num backup data."
RSYNC ${SqlTarDir}/../ "backup_data"
sleep 3
# 传输完毕后删除tar包,释放本机磁盘空间
REPORT_INFO "End rsync, delete ${SqlTarDir}/${Domain}_xbk_inc_${num}_${Date}.sql.tar.gz"
rm -f ${SqlTarDir}/${Domain}_xbk_inc_${num}_${Date}.sql.tar.gz
sleep 3
}
# 主函数
# When the incremental backup doesn't exist, the full backup fonction is called.
function MAIN
{
CHECK_SQL_TAR_DIR
CHECK_CMD
sleep 3
if [ ! -d ${XbkDir}/all ]
then
BACKUP_ALL
else
BACKUP_INC
fi
echo -e "==================================================\n"
}
#####脚本入口#####
CHECK_LOG_DIR_FILE
MAIN $1 | tee -a ${XbkLogDir}${LogFile}