#!/bin/bash


MYSQL_USER=repl
MYSQL_PASSWD=Xjb0^DDy
HOST='127.0.0.1'
USE_MEM="1024m"
IOPS=60

local_disk_name=${backup_disk:-/tmp}
local_disk_save=${local_disk_name%*/}/dbbackup_`date "+%Y-%m-%d-%H%M"`
# container_backup="dbbackup_`date "+%Y-%m-%d-%H%M"`"
container_backup="dbbackup"
recovery_backup_log="/tmp/recovery_backup.log"
>$recovery_backup_log

log() {
    local text;local logtype
    logtype=$1
    text=$2
    #其实可以再将日志的格式定义为一个字符串，这样就不用重复写`date +'%F %H:%M:%S'`\t$1\t$2\033[0m，又可以省好多代码。
    case $logtype in 
        error)
            echo -e "\033[31m`date +'%F %H:%M:%S'`[$1]\t$2\033[0m" | tee -a $recovery_backup_log;;
        info)
            echo -e "\033[32m`date +'%F %H:%M:%S'`[$1]\t$2\033[0m" | tee -a $recovery_backup_log;;
        warn)
            echo -e "\033[33m`date +'%F %H:%M:%S'`[$1]\t$2\033[0m" | tee -a $recovery_backup_log;;
    esac
}


# 在 MySQL 容器中执行命令
exec_on_container() {
    container_id=$(docker ps |grep mysql:v8 |awk '{print $1}')
    exec_sql="mysql -urepl -pXjb0^DDy -N -e"

    if [ "$1" == "sql" ];then
        docker exec  $container_id $exec_sql "$2"
    else
        docker exec  $container_id $*
    fi
}

# 检查 MGR 状态
check_mgr() {
    res=$(exec_on_container sql "select * from performance_schema.replication_group_members")
    health_num=$(echo $res | grep -o ONLINE |wc -l)
    if [ "$health_num" != "3" ];then
        # echo "MGR 集群异常，当前节点数量为: $health_num."
        log info "MGR cluster is unhealthy. Number of current nodes:$health_num. Start backup..."
    else
        if [ "$ISFORCE" != "true" ];then
            # echo "MGR 集群节点状态正常，当前节点数量为: $health_num. 无需进行数据备份及恢复，如需要强制执行，使用 -f/--force 参数."
            log error "MGR cluster is healthy. Number of current nodes:$health_num. No need for data recovery, if you need to enforce it, use the -f/--force parameter."
            exit 1;
        else
            # echo "MGR 集群节点状态正常，当前节点数量为: $health_num. 强制进行数据备份."
            log warn "MGR cluster is healthy. Number of current nodes:$health_num. Force backup..."
        fi
    fi
}


# 备份磁盘空间检查
check_disk() {
    mysql_usage=$(exec_on_container "du -shk /var/lib/mysql" | awk '{print $1}')
    # local_available=$(exec_on_container "df -T " | grep -w '/' |awk '{print $5}')
    local_available=$(df -T $local_disk_name |awk '{print $5}'|grep -o [0-9].*[0-9])

    if [ $local_available -gt $[mysql_usage*2] ];then
        # echo "磁盘空间正常，开始备份.备份存放在 $local_disk_name 下."
        log info "Disk space is ok. Backup disk is $local_disk_name."
    else
        # 是否有指定其他备份路径。是，继续；否，退出
        if [ -z $backup_disk ];then
            # echo "磁盘空间不足够存放备份，请使用 -b/--back-dir 参数指定数据存放磁盘."
            log error "Not enough disk space. Please use the -b/--back-dir parameter to specify the data storage disk."
            exit 1;
        else
            # echo "备份磁盘为 $backup_disk."
            log info "Backup disk is $local_disk_name."
        fi
    fi
}


backup() {

    mkdir -p $local_disk_save

    exec_on_container "mkdir -p /tmp/$container_backup"
    log info "Recovery Backup Start Time: `date`\n"

    # exec_on_container xtrabackup --throttle=$IOPS --use-memory=$USE_MEM  --host=$HOST \
    # --user=$MYSQL_USER --password=$MYSQL_PASSWD --backup --extra-lsndir=/${backup_disk:-tmp}/$container_backup \
    # --target-dir=/${backup_disk:-tmp}/$container_backup

    exec_on_container xtrabackup --throttle=$IOPS --use-memory=$USE_MEM  --host=$HOST \
    --user=$MYSQL_USER --password=$MYSQL_PASSWD --backup --extra-lsndir=/tmp/$container_backup/ \
    --target-dir=/tmp/$container_backup


    exec_on_container xtrabackup --prepare --target-dir=/tmp/$container_backup
    log info "Copy data to local.Please wait..."
    docker cp $container_id:/tmp/  $local_disk_save

    if [ $? != 0 ];then
        # echo "备份失败，请检查！"
        log error "Backup failed, please check the log file: $recovery_backup_log."
        exit 1;
    else
        log info "The backup has been completed. $local_disk_save"
        log info "Delete container backup file."
        exec_on_container rm -rf /tmp/*
    fi

}

rsync_backup() {
sed -i '/\[dbbackup\]/,+10d' /etc/rsyncd.conf
cat << EOF >> /etc/rsyncd.conf

[dbbackup]
path=${local_disk_save}
use chroot=yes
max nonections=4
read only=no
list=yes
uid=root
gid=root
auth users=backup
secrets file=/etc/recovery_db.passwd
EOF

echo "backup:1qaz@WSX" > /etc/recovery_db.passwd
chmod 600 /etc/recovery_db.passwd

systemctl start rsyncd
if [ $? != 0 ];then
    # echo "rsync 服务启动失败，请手动检查！"
    log error "Rsync service failed to start, please check."
    exit 1;
else
    # echo "rsync 服务端启动完成."
    log info "The rsync service is started."
fi

}


ARGS=`getopt -o b:f --long back-disk:,force-back -n 'mgr_backup.sh' -- "$@"`


if [ $? != 0 ]; then
    echo "Terminating..."
    exit 1
fi

eval set -- "${ARGS}"


while true
do
    case "$1" in
        -f|--force-back)
            ISFORCE=true
            shift
            ;;
        -b|--back-disk)
            backup_disk=$2;
            shift 2
            ;;
        --)
            shift
            break
            ;;
        *)
            log error "Parameter error!"
            exit 1
            ;;
    esac
done

#处理剩余的参数
for arg in $@
do
    # echo "无效参数 $arg"
    log error "bInvalid parameter $arg"
done

check_mgr
check_disk
backup
rsync_backup