备份mysql数据的shell脚本

保存文件:mysql_backup_centos7.sh

执行:chmod +x mysql_backup_centos7.sh

手动执行:./mysql_backup_centos7.sh

下面的数据库密码是随机密码,请重新填写测试

通过定时任务触发脚本进行执行如:每5分钟执行一次

编辑:crontab -e

输入:*/5 * * * * /usr/shell/mysql_backup_centos7.sh

查看:crontab -l

查看日志:cat /var/log/cron

bash 复制代码
#!/bin/bash
# mysql_backup_centos7.sh
# 功能:备份MySQL所有数据
# 使用:chmod +x mysql_backup_centos7.sh && ./mysql_backup_centos7.sh

# 设置颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 配置部分
MYSQL_USER="root"
MYSQL_PASSWORD="5mX2TtjmHOQWNpewXGOktA=="
BACKUP_DIR="/backup/mysql"
DATE_TAG=$(date +%Y%m%d)
BACKUP_TIME=$(date +%H%M%S)
RETENTION_DAYS=7
LOG_FILE="/var/log/mysql_backup_$(date +%Y%m%d_%H%M%S).log"

# 函数:记录日志
log_message() {
    local level=$1
    local message=$2
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo -e "${timestamp} [${level}] ${message}" | tee -a "$LOG_FILE"
}

# 函数:检查命令
check_command() {
    if ! command -v $1 &> /dev/null; then
        log_message "ERROR" "命令 $1 不存在"
        return 1
    fi
    return 0
}

# 函数:检查MySQL连接
check_mysql_connection() {
    log_message "INFO" "检查MySQL连接..."
    
    # 如果密码为空,提示输入
    if [ -z "$MYSQL_PASSWORD" ]; then
        echo -e "${YELLOW}请输入MySQL root密码: ${NC}"
        read -s MYSQL_PASSWORD
        echo
    fi
    
    # 测试连接
    if mysql -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "SELECT 1;" &>/dev/null; then
        log_message "SUCCESS" "MySQL连接成功"
        return 0
    else
        log_message "ERROR" "MySQL连接失败"
        return 1
    fi
}

# 函数:创建备份目录
create_backup_dir() {
    TODAY_BACKUP_DIR="${BACKUP_DIR}/${DATE_TAG}"
    
    if [ ! -d "$BACKUP_DIR" ]; then
        mkdir -p "$BACKUP_DIR" || {
            log_message "ERROR" "创建备份目录失败: $BACKUP_DIR"
            return 1
        }
        log_message "INFO" "创建备份目录: $BACKUP_DIR"
    fi
    
    if [ ! -d "$TODAY_BACKUP_DIR" ]; then
        mkdir -p "$TODAY_BACKUP_DIR" || {
            log_message "ERROR" "创建当天备份目录失败: $TODAY_BACKUP_DIR"
            return 1
        }
        log_message "INFO" "创建当天备份目录: $TODAY_BACKUP_DIR"
    fi
    
    echo "$TODAY_BACKUP_DIR"
}

# 函数:备份数据库结构
backup_database_structure() {
    local backup_dir=$1
    log_message "INFO" "备份数据库结构..."
    
    mysqldump -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" --all-databases --no-data \
        > "${backup_dir}/01_all_databases_structure_${BACKUP_TIME}.sql" 2>>"$LOG_FILE"
    
    if [ $? -eq 0 ]; then
        log_message "SUCCESS" "数据库结构备份完成"
        return 0
    else
        log_message "ERROR" "数据库结构备份失败"
        return 1
    fi
}

# 函数:完整备份所有数据库
backup_all_databases() {
    local backup_dir=$1
    log_message "INFO" "完整备份所有数据库..."
    
    mysqldump -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" \
        --all-databases \
        --single-transaction \
        --routines \
        --triggers \
        --events \
        --add-drop-database \
        > "${backup_dir}/02_all_databases_full_${BACKUP_TIME}.sql" 2>>"$LOG_FILE"
    
    if [ $? -eq 0 ]; then
        # 压缩备份文件
        gzip "${backup_dir}/02_all_databases_full_${BACKUP_TIME}.sql"
        log_message "SUCCESS" "完整数据库备份完成并已压缩"
        return 0
    else
        log_message "ERROR" "完整数据库备份失败"
        return 1
    fi
}

# 函数:单独备份每个数据库
backup_each_database() {
    local backup_dir=$1
    log_message "INFO" "单独备份每个数据库..."
    
    # 获取数据库列表(排除系统数据库)
    DATABASES=$(mysql -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "SHOW DATABASES;" 2>/dev/null | \
                grep -Ev "(Database|information_schema|performance_schema|mysql|sys)")
    
    if [ -z "$DATABASES" ]; then
        log_message "WARNING" "没有找到用户数据库"
        return 1
    fi
    
    local success_count=0
    local fail_count=0
    
    for DB in $DATABASES; do
        log_message "INFO" "备份数据库: $DB"
        
        # 备份单个数据库
        mysqldump -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" \
            --databases "$DB" \
            --single-transaction \
            --routines \
            --triggers \
            > "${backup_dir}/03_${DB}_${BACKUP_TIME}.sql" 2>>"$LOG_FILE"
        
        if [ $? -eq 0 ]; then
            # 压缩备份文件
            gzip "${backup_dir}/03_${DB}_${BACKUP_TIME}.sql"
            log_message "SUCCESS" "数据库 $DB 备份完成"
            success_count=$((success_count + 1))
        else
            log_message "ERROR" "数据库 $DB 备份失败"
            fail_count=$((fail_count + 1))
        fi
    done
    
    log_message "INFO" "数据库备份统计: 成功 $success_count 个, 失败 $fail_count 个"
    return $fail_count
}

# 函数:备份用户权限
backup_user_grants() {
    local backup_dir=$1
    log_message "INFO" "备份MySQL用户权限..."
    
    mysql -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" --skip-column-names -A \
        -e"SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user NOT IN ('mysql.sys','mysql.session','mysql.infoschema')" 2>/dev/null | \
        mysql -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" --skip-column-names -A 2>/dev/null | \
        sed 's/$/;/g' > "${backup_dir}/04_mysql_grants_${BACKUP_TIME}.sql" 2>>"$LOG_FILE"
    
    if [ $? -eq 0 ]; then
        log_message "SUCCESS" "用户权限备份完成"
        return 0
    else
        log_message "ERROR" "用户权限备份失败"
        return 1
    fi
}

# 函数:备份配置文件
backup_config_files() {
    local backup_dir=$1
    log_message "INFO" "备份MySQL配置文件..."
    
    # 创建配置文件目录
    CONFIG_DIR="${backup_dir}/config"
    mkdir -p "$CONFIG_DIR"
    
    local backed_up=0
    
    # 备份主配置文件
    if [ -f "/etc/my.cnf" ]; then
        cp /etc/my.cnf "${CONFIG_DIR}/my.cnf"
        log_message "INFO" "已备份: /etc/my.cnf"
        backed_up=$((backed_up + 1))
    fi
    
    # 备份配置目录
    if [ -d "/etc/my.cnf.d" ]; then
        cp -r /etc/my.cnf.d "${CONFIG_DIR}/"
        log_message "INFO" "已备份: /etc/my.cnf.d"
        backed_up=$((backed_up + 1))
    fi
    
    # 备份日志文件(可选)
    if [ -f "/var/log/mysqld.log" ]; then
        cp /var/log/mysqld.log "${CONFIG_DIR}/mysqld.log"
        log_message "INFO" "已备份: /var/log/mysqld.log"
        backed_up=$((backed_up + 1))
    fi
    
    if [ $backed_up -gt 0 ]; then
        log_message "SUCCESS" "配置文件备份完成 (共 $backed_up 个文件)"
        return 0
    else
        log_message "WARNING" "未找到配置文件"
        return 1
    fi
}

# 函数:创建恢复脚本
create_restore_script() {
    local backup_dir=$1
    local backup_time=$2
    
    cat > "${backup_dir}/restore_mysql.sh" << 'EOF'
#!/bin/bash
# MySQL恢复脚本

set -e

BACKUP_DIR=$(cd "$(dirname "$0")" && pwd)
echo "备份目录: $BACKUP_DIR"

# 显示备份文件
echo "可用的备份文件:"
echo "----------------------------------------"
ls -1 "$BACKUP_DIR"/*.gz 2>/dev/null | while read -r file; do
    filename=$(basename "$file")
    size=$(du -h "$file" | cut -f1)
    echo "  $filename ($size)"
done
echo "----------------------------------------"

# 选择备份文件
if [ $# -eq 1 ]; then
    BACKUP_FILE="$1"
else
    read -p "请输入要恢复的备份文件名: " BACKUP_FILE
fi

# 检查文件是否存在
if [ ! -f "${BACKUP_DIR}/${BACKUP_FILE}" ] && [ ! -f "$BACKUP_FILE" ]; then
    echo "错误: 备份文件不存在"
    exit 1
fi

if [ ! -f "$BACKUP_FILE" ]; then
    BACKUP_FILE="${BACKUP_DIR}/${BACKUP_FILE}"
fi

echo "准备恢复数据库..."
echo "备份文件: $BACKUP_FILE"

# 获取MySQL信息
read -p "MySQL主机 (默认: localhost): " MYSQL_HOST
MYSQL_HOST=${MYSQL_HOST:-localhost}
read -p "MySQL端口 (默认: 3306): " MYSQL_PORT
MYSQL_PORT=${MYSQL_PORT:-3306}
read -p "MySQL用户名 (默认: root): " MYSQL_USER
MYSQL_USER=${MYSQL_USER:-root}
read -s -p "MySQL密码: " MYSQL_PASSWORD
echo

# 测试连接
echo "测试数据库连接..."
if ! mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "SELECT 1;" &>/dev/null; then
    echo "错误: 数据库连接失败"
    exit 1
fi

# 确认恢复
echo -e "\n警告: 此操作将覆盖现有数据库数据!"
read -p "确认要恢复吗?(输入 'YES' 继续): " CONFIRM
if [ "$CONFIRM" != "YES" ]; then
    echo "操作已取消"
    exit 0
fi

# 执行恢复
echo "正在恢复数据库..."
start_time=$(date +%s)

gunzip -c "$BACKUP_FILE" | mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASSWORD"

end_time=$(date +%s)
duration=$((end_time - start_time))

if [ $? -eq 0 ]; then
    echo -e "\n✅ 数据库恢复成功!"
    echo "   耗时: ${duration}秒"
    echo "   备份文件: $(basename "$BACKUP_FILE")"
else
    echo -e "\n❌ 数据库恢复失败!"
    exit 1
fi
EOF
    
    chmod +x "${backup_dir}/restore_mysql.sh"
    log_message "INFO" "恢复脚本已创建: ${backup_dir}/restore_mysql.sh"
}

# 函数:清理旧备份
cleanup_old_backups() {
    log_message "INFO" "清理 $RETENTION_DAYS 天前的旧备份..."
    
    if [ -d "$BACKUP_DIR" ]; then
        local deleted_count=0
        find "$BACKUP_DIR" -maxdepth 1 -type d -name "2*" -mtime +$RETENTION_DAYS 2>/dev/null | while read -r old_dir; do
            log_message "INFO" "删除旧备份: $old_dir"
            rm -rf "$old_dir"
            deleted_count=$((deleted_count + 1))
        done
        
        if [ $deleted_count -gt 0 ]; then
            log_message "SUCCESS" "已清理 $deleted_count 个旧备份"
        else
            log_message "INFO" "没有需要清理的旧备份"
        fi
    fi
}

# 函数:显示备份报告
show_backup_report() {
    local backup_dir=$1
    local start_time=$2
    
    local end_time=$(date +%s)
    local duration=$((end_time - start_time))
    
    # 计算备份大小
    local backup_size=$(du -sh "$backup_dir" 2>/dev/null | awk '{print $1}')
    local backup_count=$(find "$backup_dir" -name "*.gz" -o -name "*.sql" 2>/dev/null | wc -l)
    
    echo -e "\n${GREEN}=== 备份完成报告 ===${NC}"
    echo -e "${BLUE}备份目录:${NC} $backup_dir"
    echo -e "${BLUE}备份时间:${NC} $(date '+%Y-%m-%d %H:%M:%S')"
    echo -e "${BLUE}耗时:${NC} ${duration}秒"
    echo -e "${BLUE}备份大小:${NC} ${backup_size:-0}"
    echo -e "${BLUE}文件数量:${NC} ${backup_count}个"
    echo -e "${BLUE}日志文件:${NC} $LOG_FILE"
    
    # 显示备份文件列表
    echo -e "\n${BLUE}备份文件列表:${NC}"
    find "$backup_dir" -type f \( -name "*.gz" -o -name "*.sql" \) 2>/dev/null | sort | while read -r file; do
        local size=$(du -h "$file" 2>/dev/null | cut -f1)
        echo "  $(basename "$file") (${size})"
    done
    
    echo -e "\n${GREEN}✅ 备份完成!${NC}"
}

# 主函数
main() {
    echo -e "${GREEN}=== MySQL备份脚本 ===${NC}"
    echo -e "开始时间: $(date '+%Y-%m-%d %H:%M:%S')"
    echo -e "备份目录: $BACKUP_DIR"
    echo
    
    local start_time=$(date +%s)
    
    # 检查是否为root用户
    if [ "$(id -u)" != "0" ]; then
        echo -e "${RED}错误: 此脚本需要root权限${NC}"
        exit 1
    fi
    
    # 检查mysqldump命令
    if ! check_command "mysqldump"; then
        echo -e "${RED}错误: mysqldump命令不存在,请先安装MySQL客户端${NC}"
        exit 1
    fi
    
    # 检查MySQL连接
    if ! check_mysql_connection; then
        echo -e "${RED}错误: 无法连接到MySQL,请检查配置${NC}"
        exit 1
    fi
    
    # 创建备份目录
    TODAY_BACKUP_DIR=$(create_backup_dir)
    if [ $? -ne 0 ]; then
        exit 1
    fi
    
    # 执行备份
    log_message "INFO" "开始备份MySQL数据..."
    
    # 1. 备份数据库结构
    backup_database_structure "$TODAY_BACKUP_DIR"
    
    # 2. 完整备份所有数据库
    backup_all_databases "$TODAY_BACKUP_DIR"
    
    # 3. 单独备份每个数据库
    backup_each_database "$TODAY_BACKUP_DIR"
    
    # 4. 备份用户权限
    backup_user_grants "$TODAY_BACKUP_DIR"
    
    # 5. 备份配置文件
    backup_config_files "$TODAY_BACKUP_DIR"
    
    # 6. 创建恢复脚本
    create_restore_script "$TODAY_BACKUP_DIR" "$BACKUP_TIME"
    
    # 7. 清理旧备份
    cleanup_old_backups
    
    # 显示报告
    show_backup_report "$TODAY_BACKUP_DIR" "$start_time"
    
    return 0
}

# 执行主函数
main
相关推荐
eggwyw14 分钟前
MySQL-练习-数据汇总-CASE WHEN
数据库·mysql
mygljx3 小时前
MySQL 数据库连接池爆满问题排查与解决
android·数据库·mysql
Bdygsl4 小时前
MySQL(1)—— 基本概念和操作
数据库·mysql
身如柳絮随风扬4 小时前
什么是左匹配规则?
数据库·sql·mysql
jiankeljx4 小时前
mysql之如何获知版本
数据库·mysql
小李来了!5 小时前
数据库DDL、DML、DQL、DCL详解
数据库·mysql
我科绝伦(Huanhuan Zhou)6 小时前
【生产案例】MySQL InnoDB 数据损坏崩溃修复
数据库·mysql·adb
海棠蚀omo6 小时前
从零敲开 MySQL 的大门:库与表的基础操作实战(保姆级入门指南)
数据库·mysql
廋到被风吹走7 小时前
【MySql】超时问题分析
java·数据库·mysql
y = xⁿ7 小时前
重生之我创作出了小红书:对象存储模块,用户资料模块
后端·mysql·intellij-idea