多功能mysql备份shell

最新代码在https://github.com/crjfans/mysqlbackup

#!/bin/bash

########################################################################
# script name: mysqlbackup.sh                                            #
# function: use this script to make mysql backups                      #
# useage: mysqlbackup.sh -a [-e -d -e ...]                               #
# version: v0.1                                                        #
# created date: 2016/1/6                                               #
# author: JayZhou                                                      #
########################################################################

#set -e: if the execution result of then instruction is not equle 0 ,then exit automatically
#set -e
#set -u: if the variable to be used is not be define,you will get an error message.
set -u
PREFIX_ERROR="ERROR"
PREFIX_WARNING="WARNING"
PREFIX_NOTICE="NOTICE"
EXIT_NORMAL=0
EXIT_ERROR=1
CONFIG_DIR=/etc
CONFIG_FILE=${CONFIG_DIR}/mysqlbackup.cfg
TEMP_FILE_FLAG=temp
CONFIG_FILE_TEMP=${CONFIG_FILE}.${TEMP_FILE_FLAG}
BACKUP_START_MSG='echo [`date +%Y%m%d-%H:%M:%S`]:START to backup...'
BACKUP_FINISH_MSG='echo [`date +%Y%m%d-%H:%M:%S`]:FINISH backup!'
TIME='date +%Y%m%d'

########################################################################
# routine name: usage_notes
# function: to show how to use the script
########################################################################
function usage_notes()
{
echo "  Usage: `basename $0` [OPTION] [DB1 DB2...] [TABLE1 TABLE2...] [...]"
echo "  Options:
    -a           Generate backups of all databases.
    -e           Generate backups of each database.
    -d value[s]  Generate backups of single/multi database[s].
                 Example: -d 'mydb1 mydb2'
    -t value[s]  Generate backups of single/multi table[s] of single database.
                 Example: -t 'mydb1 mytable1'
    -b           Generate backups of binlog for each database.
    -h           Generate backups of binlog use copy command.
    -c value     Clean up dump backups beyond n(n must be integer) days ago.
                 Example: -c 7
    -f value     Clean up binlog backups beyond n(n must be integer) days ago.
                 Example: -f 7
    -g           Flush binary logs
    -p           Create mysql password for dumping
  Options must be given as -option ['value1 [value2] ...'] or -option value, not -option=value.
"
exit 0
}

########################################################################
# routine name: exec_msg
# function: to judge whether the command called executed successfully
########################################################################
function exec_msg()
{
    EXEC_MSG_STATUS=$1
    EXEC_MSG_SUCCESS=`echo $2 | awk -F"@" '{print $1}'`
    EXEC_COMMAND_SUCCESS=`echo $2 | awk -F"@" '{print $2}'`
    EXEC_MSG_ERROR=`echo $3 | awk -F"@" '{print $1}'`
    EXEC_COMMAND_ERROR=`echo $3 | awk -F"@" '{print $2}'`
        if [ ${EXEC_MSG_STATUS} -eq 0 ]; then
            if [ ! -z ${EXEC_MSG_SUCCESS:0:1} ]; then
                    echo "${PREFIX_NOTICE}:${EXEC_MSG_SUCCESS}"
            if [ ! -z ${EXEC_COMMAND_SUCCESS:0:1} ]; then
                        eval ${EXEC_COMMAND_SUCCESS}
            fi
        fi
        else
            if [ ! -z ${EXEC_MSG_ERROR:0:1} ]; then
                    echo "${PREFIX_ERROR}:${EXEC_MSG_ERROR}"
            if [ ! -z ${EXEC_COMMAND_ERROR:0:1} ]; then
                        eval ${EXEC_COMMAND_ERROR}
            fi
        fi
                exit $EXIT_ERROR
        fi
}

########################################################################
# routine name: create_passwd
# function: create password file for dumping
########################################################################
function create_passwd()
{
    if [ ! -d $DIR_PASSWD ]; then
        mkdir -p $DIR_PASSWD
    fi
        echo -n "Please enter MySQL(user=root)'s password:"
        read -s -a MYSQL_PASSWD
    echo ""
    $CMD_MYSQL -uroot -p$MYSQL_PASSWD -N -s -e "select user()" >/dev/null 2>&1
    exec_msg "$?" "" "the password of root is wrong!"
    echo "root $MYSQL_PASSWD" |  $CMD_OPENSSL aes-128-cbc -k $HOSTNAME -base64 > $FILE_PASSWD && chmod 600 $FILE_PASSWD
    exec_msg "$?" "create the password file successfully!" ""
}

########################################################################
# routine name: create_config_file
# function: create a template config file
########################################################################
function create_config_file()
{
        #initialize config file
        if [ ! -w $CONFIG_DIR ]; then
                echo "$PREFIX_ERROR:create $CONFIG_FILE fail,no privilege to write $CONFIG_DIR!"
                exit $EXIT_ERROR
        fi
        echo "$PREFIX_ERROR:Not found ${CONFIG_FILE} ,create a template now..."
        echo '#mysql data directory
DIR_MYSQL="/var/lib/mysql"

#the directory where you want to save the mysql dumping files
DIR_BACKUP="/tmp/backupdb"

#the directory where you want to save the mysql binlog files
DIR_BACKUP_BINLOG="$DIR_BACKUP/binlog"

#the directory where you want to save the password of mysql
DIR_PASSWD="$DIR_MYSQL/etc"

#the file you want to save the password of mysql
FILE_PASSWD="$DIR_PASSWD/passwordfile"

#the file contain all the names of binlog files
FILE_BINLOG_INDEX="$DIR_MYSQL/mysql-bin.index"

#the location of the "mysqldump" command
CMD_MYSQLDUMP="/usr/bin/mysqldump"

#the location of the "mysqlbinlog" command
CMD_MYSQLBINLOG="/usr/bin/mysqlbinlog"

#the location of the "mysql" command
CMD_MYSQL="/usr/bin/mysql"

#the location of the "openssl" command used to encrypt password
CMD_OPENSSL="/usr/bin/openssl"

#the databases specified will be dumped
LIST_INCLUDE_DB_DUMP="(mydb1|mydb2|mydb3)"

#the binlog files backups of databases specified will be generated
LIST_INCLUDE_DB_BINLOG="(mydb1|mydb2|mydb3)"

#the socket file of mysql you want to connect
SOCKET="/var/lib/mysql/mysql.sock"' > $CONFIG_FILE_TEMP
        echo "$PREFIX_NOTICE:create $CONFIG_FILE_TEMP successfully!"
        echo "$PREFIX_WARNING:you need to [1]change the file name from $CONFIG_FILE_TEMP to $CONFIG_FILE [2]change the default values against your actual conditions!"
        exit $EXIT_NORMAL
}

########################################################################
# routine name: check_init_value
# function: check initial variables
########################################################################
function check_init_value()
{
    #check password file
    if [ ! -f $FILE_PASSWD ]; then
        echo "$PREFIX_ERROR:Not found the password file,please create it by: $0 -p"
        exit 0
    fi
    #check backup dir
    if [ ! -d $DIR_BACKUP ]; then
        echo "$PREFIX_WARNING:not found the backup directory,create it now..."
        mkdir -p $DIR_BACKUP
        exec_msg "$?" "create backup directory successfully!" ""
    fi
}

########################################################################
# routine name: init_var
# function: import variables in mysqlbackup.cnf
########################################################################
function init_var()
{
        if [ -r $CONFIG_FILE ]; then
                #import variables to current environment
                . $CONFIG_FILE
        exec_msg "$?" "" "Initialize variables failed!"
        elif [ -r $CONFIG_FILE_TEMP ]; then
        echo "${PREFIX_ERROR}:you must ensure all variables in $CONFIG_FILE_TEMP are correct,and then change the name of $CONFIG_FILE_TEMP to $CONFIG_FILE"
        exit 1
        else
        if [ ! -f $CONFIG_FILE ]; then
            create_config_file
        else
                    echo "$PREFIX_ERROR:You have no permission to read $CONFIG_FILE !"
            exit 0
        fi
        fi
}

########################################################################
# routine name: flush_bin_log
# function: Initialize the CMD_DUMP command
########################################################################
function flush_bin_log()
{
        #get user and password from password file
        USER=`cat $FILE_PASSWD | $CMD_OPENSSL aes-128-cbc -d -k $HOSTNAME -base64 | awk '{print $1}'`
        PASSWD=`cat $FILE_PASSWD | $CMD_OPENSSL aes-128-cbc -d -k $HOSTNAME -base64 | awk '{print $2}'`
        #if turned on the log_bin,add a parameter:'--master-data=2' to CMD_DUMP
        `$CMD_MYSQL -u$USER -p$PASSWD -N -s -e "flush binary logs"`
        exec_msg "$?" "successfully flush binary logs!" "failed to flush binary logs! check your password!"
}

########################################################################
# routine name: init_dump
# function: Initialize the CMD_DUMP command
########################################################################
function init_dump()
{
    #get user and password from password file
    USER=`cat $FILE_PASSWD | $CMD_OPENSSL aes-128-cbc -d -k $HOSTNAME -base64 | awk '{print $1}'`
    PASSWD=`cat $FILE_PASSWD | $CMD_OPENSSL aes-128-cbc -d -k $HOSTNAME -base64 | awk '{print $2}'`
    #if turned on the log_bin,add a parameter:'--master-data=2' to CMD_DUMP
    LOGBIN_STATUS=`$CMD_MYSQL -u$USER -p$PASSWD -N -s -e "SHOW VARIABLES LIKE 'log_bin'" | awk '{print $2}'`
    exec_msg "$?" "" "failed to get the mysql variable:log_bin! check your password!"
    if [ $LOGBIN_STATUS = "ON" ]; then
        MASTER='--master-data=2'
    else
        MASTER=' '
    fi
    #Initialize the CMD_DUMP command
    CMD_DUMP="$CMD_MYSQLDUMP -u$USER -p$PASSWD -x -R $MASTER --socket=$SOCKET --default-character-set=utf8"
}

########################################################################
# routine name: backup_all
# function: generate backup for all databases
########################################################################
function backup_all()
{
    init_dump
    DUMP_FILE=${DIR_BACKUP}/`${TIME}`.${HOSTNAME}.all.sql
    eval ${BACKUP_START_MSG}
    $CMD_DUMP -A  > $DUMP_FILE
    exec_msg "$?" "generate backup:$DUMP_FILE successfully!" "fail to generate backup!@rm -rf $DUMP_FILE"
    DUMP_FILE_NEW=${DIR_BACKUP}/`tail -n 1 $DUMP_FILE |awk '{print $5"."$6}'`.${HOSTNAME}.all.sql
    mv $DUMP_FILE $DUMP_FILE_NEW
    gzip -f $DUMP_FILE_NEW
    exec_msg "$?" "" "fail to compress backup!"
    sleep 5
    eval ${BACKUP_FINISH_MSG}
}

########################################################################
# routine name: backup_each
# function: generate backup for each database
########################################################################
function backup_each()
{
    init_dump
    eval $BACKUP_START_MSG
    for db in $($CMD_MYSQL -u$USER -p$PASSWD -N -s -e "SHOW DATABASES"|egrep -w $LIST_INCLUDE_DB_DUMP)
    do
        DUMP_FILE=${DIR_BACKUP}/`${TIME}`.${HOSTNAME}.${db}.sql
        $CMD_DUMP $db --databases > $DUMP_FILE
        exec_msg "$?" "generate backup:$DUMP_FILE successfully!" "fail to generate backup!@rm -rf $DUMP_FILE"
        DUMP_FILE_NEW=${DIR_BACKUP}/`tail -n 1 $DUMP_FILE |awk '{print $5"."$6}'`.${HOSTNAME}.${db}.sql
        mv $DUMP_FILE $DUMP_FILE_NEW
        gzip -f $DUMP_FILE_NEW
        exec_msg "$?" "" "fail to compress backup!"
    done
    eval ${BACKUP_FINISH_MSG}
}

########################################################################
# routine name: backup_db
# function: generate backup for database[s] selected
########################################################################
function backup_db()
{
    init_dump
    #use "grep" to remove head spaces and tail spaces,use "sed" to replace spaces between strings to one colon
    DUMP_FILE_POSTFIX=`echo "${OPTARG}" | grep -o "[^ ]\+\( \+[^ ]\+\)*" | sed 's/[ ][ ]*/:/g'`.sql
    DUMP_FILE=${DIR_BACKUP}/`${TIME}`.${DUMP_FILE_POSTFIX}
    eval $BACKUP_START_MSG
    $CMD_DUMP --databases $OPTARG > $DUMP_FILE
    exec_msg "$?" "generate backup:$DUMP_FILE successfully!" "fail to generate backup!@rm -rf $DUMP_FILE"
    DUMP_FILE_NEW=${DIR_BACKUP}/`tail -n 1 $DUMP_FILE | awk '{print $5"."$6}'`.${DUMP_FILE_POSTFIX}
    mv $DUMP_FILE $DUMP_FILE_NEW
    gzip -f $DUMP_FILE_NEW
    exec_msg "$?" "" "fail to compress backup!"
    eval ${BACKUP_FINISH_MSG}
}

########################################################################
# routine name: backup_dt
# function: generate backup for database table[s]
########################################################################
function backup_dt()
{
    init_dump
    #use "grep" to remove head spaces and tail spaces,use "sed" to replace spaces between strings to one colon
    DUMP_TB=`echo "${OPTARG}" | grep -o "[^ ]\+\( \+[^ ]\+\)*" | sed 's/[ ][ ]*/:/g'|awk -F":" '{$1="";print}'|grep -o "[^ ]\+\( \+[^ ]\+\)*" | sed 's/[ ][ ]*/:/g'`
    DUMP_DB=`echo "${OPTARG}" | grep -o "[^ ]\+\( \+[^ ]\+\)*" | sed 's/[ ][ ]*/:/g'|awk -F":" '{print $1}'`
    DUMP_FILE_POSTFIX=${HOSTNAME}.${DUMP_DB}.${DUMP_TB}.sql
    DUMP_FILE=${DIR_BACKUP}/`${TIME}`.${DUMP_FILE_POSTFIX}
    $CMD_DUMP $OPTARG > $DUMP_FILE
    exec_msg "$?" "generate backup:$DUMP_FILE successfully!" "fail to generate backup!@rm -rf $DUMP_FILE"
    DUMP_FILE_NEW=${DIR_BACKUP}/`tail -n 1 $DUMP_FILE |awk '{print $5"."$6}'`.${DUMP_FILE_POSTFIX}
    mv $DUMP_FILE $DUMP_FILE_NEW
    gzip -f $DUMP_FILE_NEW
    exec_msg "$?" "" "fail to compress backup!"
    eval ${BACKUP_FINISH_MSG}
}

########################################################################
# routine name: backup_binlog
# function: generate backup for binlog
########################################################################
function backup_binlog()
{
    USER=`cat $FILE_PASSWD | $CMD_OPENSSL aes-128-cbc -d -k $HOSTNAME -base64 | awk '{print $1}'`
    PASSWD=`cat $FILE_PASSWD | $CMD_OPENSSL aes-128-cbc -d -k $HOSTNAME -base64 | awk '{print $2}'`
    BACPUP_BINLOG_START_TIME=$(date -d "24 hour ago $(date +%Y%m%d)" +%Y-%m-%d\ %H:%M:%S)
    BACPUP_BINLOG_STOP_TIME=$(date -d "1 second ago $(date +%Y%m%d)" +%Y-%m-%d\ %H:%M:%S)
    #check whether the binlog backup dir exists,and create one
    if [ ! -d $DIR_BACKUP_BINLOG ]; then
                echo "$PREFIX_NOTICE:create the binlog backup directory [$DIR_BACKUP_BINLOG] now..."
                mkdir -p $DIR_BACKUP_BINLOG
                exec_msg "$?" "create binlog backup directory successfully!" ""
        fi
    #check whether the binlog index file exists
    if [ ! -r ${FILE_BINLOG_INDEX} ]; then
                exec_msg "1" "" "the file ${FILE_BINLOG_INDEX} is not found,please check ${CONFIG_FILE} or my.cnf file."
        fi
    eval $BACKUP_START_MSG
    for db in $($CMD_MYSQL -u$USER -p$PASSWD -N -s -e "SHOW DATABASES"|egrep -w $LIST_INCLUDE_DB_BINLOG)
    do
        BACKUP_BINLOG_FILE=${DIR_BACKUP_BINLOG}/$(date -d "24 hour ago" +%Y%m%d).${HOSTNAME}.${db}.binlog
        #clean the BACKUP_BINLOG_FILE
        > $BACKUP_BINLOG_FILE
        for BINLOG_FILE in $(awk -F'/' '{print $NF}' $FILE_BINLOG_INDEX)
        do
            BINLOG_FILE=$(dirname ${FILE_BINLOG_INDEX})/$BINLOG_FILE
            $CMD_MYSQLBINLOG -d $db --start-datetime="$BACPUP_BINLOG_START_TIME" --stop_datetime="$BACPUP_BINLOG_STOP_TIME" $BINLOG_FILE  >> $BACKUP_BINLOG_FILE
            exec_msg "$?" "" "fail to generate binlog backup,from ${BINLOG_FILE} to ${BACKUP_BINLOG_FILE}!@rm -rf $BACKUP_BINLOG_FILE"
            gzip -f $BACKUP_BINLOG_FILE
            exec_msg "$?" "" "fail to compress binlog backup!"
        done
        exec_msg "$?" "generate binlog backup:$BACKUP_BINLOG_FILE successfully!" ""
    done
    eval ${BACKUP_FINISH_MSG}
}

########################################################################
# routine name: backup_binlog
# function: generate backup for binlog
########################################################################
function backup_binlog_file()
{
    #flush binary logs
    flush_bin_log
        #check whether the binlog backup dir exists,and create one
        if [ ! -d $DIR_BACKUP_BINLOG ]; then
                echo "$PREFIX_NOTICE:create the binlog backup directory [$DIR_BACKUP_BINLOG] now..."
                mkdir -p $DIR_BACKUP_BINLOG
                exec_msg "$?" "create binlog backup directory successfully!" ""
        fi
        #check whether the binlog index file exists
        if [ ! -r ${FILE_BINLOG_INDEX} ]; then
                exec_msg "1" "" "the file ${FILE_BINLOG_INDEX} is not found,please check ${CONFIG_FILE} or my.cnf file."
        fi
    #find begin and end index of binlog file to backup
    BACK_BINLOG_INDEX=$DIR_BACKUP_BINLOG/mysql-bin-backup.index
    if [ -r $BACK_BINLOG_INDEX ];then
        BACKED_BINLOG_FILE=$(tail -n 1 $BACK_BINLOG_INDEX)
        BACK_BINLOG_INDEX_BEGIN_NUM=$(grep -n $BACKED_BINLOG_FILE $FILE_BINLOG_INDEX | awk -F':' '{print $1}')
        if [ -z $BACK_BINLOG_INDEX_BEGIN_NUM ];then
            BACK_BINLOG_INDEX_BEGIN_NUM=0
        fi
    else
        BACK_BINLOG_INDEX_BEGIN_NUM=0
    fi
    BACK_BINLOG_INDEX_END_NUM=$(wc -l ${FILE_BINLOG_INDEX} | awk '{print $1}')
    BINLOG_FILE=""
    #begin backup binlog file
        eval $BACKUP_START_MSG
        for BINLOG_FILE in $(cat $FILE_BINLOG_INDEX | awk "NR > $BACK_BINLOG_INDEX_BEGIN_NUM && NR < $BACK_BINLOG_INDEX_END_NUM")
        do
            BINLOG_FILE=$(dirname ${FILE_BINLOG_INDEX})/$BINLOG_FILE
            BACKUP_BINLOG_FILE=$DIR_BACKUP_BINLOG/$(date +%Y%m%d%H%M%S).${HOSTNAME}.`basename ${BINLOG_FILE}`
            cp $BINLOG_FILE $BACKUP_BINLOG_FILE
            exec_msg "$?" "" "fail to generate binlog backup:fail to copy $BINLOG_FILE to $DIR_BACKUP_BINLOG"
        echo `basename ${BINLOG_FILE}` >> $BACK_BINLOG_INDEX
        gzip -f $BACKUP_BINLOG_FILE
        exec_msg "$?" "" "fail to compress binlog backup!"
        exec_msg "$?" "generate binlog backup:${BACKUP_BINLOG_FILE} successfully!" ""
    done
    if [ -z $BINLOG_FILE ];then
        echo "$PREFIX_NOTICE:no binlog file need to be backup."
    fi
        eval ${BACKUP_FINISH_MSG}
}

########################################################################
# routine name: backup_dump_clean
# function: clean up dumping backups beyond n days
########################################################################
function backup_dump_clean()
{
    DELETE_CNT=`find ${DIR_BACKUP} -mtime +$OPTARG -type f  | wc -l`
    if [ ${DELETE_CNT} -gt 0 ]; then
        echo "$PREFIX_NOTICE:find ${DELETE_CNT} dumping-backups $OPTARG days ago from ${DIR_BACKUP}, need to delete."
        find ${DIR_BACKUP} -mtime +$OPTARG -type f |xargs -i rm {} -f
        exec_msg "$?" "clean up ${DELETE_CNT} dumping backup files successfully!" "fail to clean up the dumping backup files!"
    else
        echo "$PREFIX_NOTICE:dumping-backups $OPTARG days ago are not found in ${DIR_BACKUP}, need not to delete."
    fi
}


########################################################################
# routine name: backup_binlog_clean
# function: clean up binlog backups beyond n days
########################################################################
function backup_binlog_clean()
{
        DELETE_CNT=`find ${DIR_BACKUP_BINLOG} -mtime +$OPTARG -type f  | wc -l`
    if [ ${DELETE_CNT} -gt 0 ]; then
        echo "$PREFIX_NOTICE:find ${DELETE_CNT} binlog-backups $OPTARG days ago from ${DIR_BACKUP_BINLOG}, need to delete."
            find ${DIR_BACKUP_BINLOG} -mtime +$OPTARG -type f |xargs -i rm {} -f
            exec_msg "$?" "clean ${DELETE_CNT} binlog backup files successfully!" "fail to clean the binlog backup files!"
    else
        echo "$PREFIX_NOTICE:binlog-backups $OPTARG days ago are not found in ${DIR_BACKUP_BINLOG,} need not to delete."
    fi
}

########################################################################
# script entry
########################################################################
if [ $# -eq 0 ]; then
        usage_notes
else
        init_var
        while getopts :aed:t:bhc:f:pg varname
        do
        case $varname in
                    a)  check_init_value; backup_all; ;;
                    e)  check_init_value; backup_each; ;;
                    d)  check_init_value; backup_db; ;;
                    t)  check_init_value; backup_dt; ;;
                    b)  check_init_value; backup_binlog; ;;
                    h)  check_init_value; backup_binlog_file; ;;
                    c)  check_init_value; backup_dump_clean; ;;
                    f)  check_init_value; backup_binlog_clean; ;;
                    g)  check_init_value; flush_bin_log; ;;
                    p)  create_passwd; ;;
                    *)  echo "$PREFIX_ERROR:wrong parameters"; usage_notes;
        esac
    done
fi
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值