备份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
相关推荐
一招定胜负2 小时前
navicat连接数据库&mysql常见语句及操作
数据库·mysql
sayyy4 小时前
【Docker】 安装 mysql8.0
mysql·docker
CodeAmaz4 小时前
MySQL索引,以及它们的好处和坏处
数据库·mysql·面试题·索引
四谎真好看5 小时前
MySQL学习笔记(基础篇1)
笔记·学习·mysql·学习笔记
小毅&Nora5 小时前
【后端】【JAVA】MySQL面试题深度解析:50道高频真题全解
java·mysql·面试
帝吃藕和7 小时前
MySQL 知识点复习- 2.创建数据表及查询
数据库·mysql
怒放de生命20107 小时前
mysql8安装后忘记密码,大小写不敏感修改,修改端口号,开启远程访问
mysql
ruleslol7 小时前
mysql-使用 performance_schema 进行性能监控
mysql
半夏知半秋8 小时前
mysql相关知识点学习整理
服务器·开发语言·数据库·sql·学习·mysql