当前位置: 首页 > news >正文

mysql全屏终端全量、部分备份、恢复脚本

思路:
备份前会自动校验是否有需要清理的文件


两种使用方式:
./mysql_backup.sh 进入终端交互模式

./mysql_backup.sh 参数 ,案例:./mysql_backup.sh 1 ,执行全量备份


后台运行,查看日志案例:

# 后台运行全量备份,日志输出到文件
nohup ./mysql_backup.sh 1 > mysql_backup.log 2>&1 &

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

touch mysql_backup.sh && chmod +x mysql_backup.sh
#!/bin/bash# MySQL备份恢复脚本
# 支持全量备份、部分库备份、备份恢复、自动清理
# Author: System Administrator
# Version: 1.0# ===============================================
# 配置参数 - 请根据实际环境修改
# ===============================================# MySQL连接配置
MYSQL_USER="root"           # MySQL用户名
MYSQL_PASS="cnmsb123"           # MySQL密码
MYSQL_HOST="localhost"      # MySQL主机地址,默认本机
MYSQL_PORT="3306"           # MySQL端口,默认3306# 备份配置
BACKUP_DIR="/opt"           # 备份文件存储目录
RETENTION_DAYS=7            # 备份文件保留天数,超过此天数的备份将被自动清理# 部分备份排除数据库配置
# 在进行部分备份时,以下数据库将被排除(不进行备份)
# 可以根据需要修改此列表,多个数据库用逗号分隔,例如:a,b,c      #代表排除a,b,c再备份
EXCLUDE_DATABASES=""# 备份选项配置
MYSQLDUMP_OPTIONS="--single-transaction --routines --triggers --set-gtid-purged=OFF"  # mysqldump额外选项# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
WHITE='\033[1;37m'
NC='\033[0m' # No Color# 动画字符
SPINNER='|/-\'# 打印带颜色的文本
print_color() {local color=$1local text=$2echo -e "${color}${text}${NC}"
}# 清屏并移动光标到顶部
clear_screen() {clearprintf "\033[H"
}# 获取终端尺寸
get_terminal_size() {TERM_COLS=$(tput cols 2>/dev/null || echo 80)TERM_ROWS=$(tput lines 2>/dev/null || echo 24)
}# 居中显示文本
center_text() {local text="$1"local color="$2"local padding=$(( (TERM_COLS - ${#text}) / 2 ))printf "%*s" $padding ""print_color "$color" "$text"
}# 绘制分隔线
draw_line() {local char="${1:-═}"local color="${2:-$CYAN}"printf "${color}"for ((i=1; i<=TERM_COLS; i++)); doprintf "$char"doneprintf "${NC}\n"
}# 绘制边框
draw_border() {local title="$1"draw_line "═" "$CYAN"echo ""center_text "$title" "$WHITE"echo ""draw_line "═" "$CYAN"
}# 全屏标题
print_title() {clear_screenget_terminal_sizeecho ""draw_border "MySQL 备份恢复管理工具 v1.0"echo ""# 显示系统信息center_text "🖥️  系统: $(uname -s) $(uname -r)" "$CYAN"center_text "📅 时间: $(date '+%Y-%m-%d %H:%M:%S')" "$CYAN"center_text "👤 用户: $(whoami)@$(hostname)" "$CYAN"echo ""draw_line "─" "$BLUE"
}# 高级进度条动画
show_progress() {local message=$1local process_pid=$2local spinner_chars="⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"local delay=0.1local spin_i=0echo -n -e "${YELLOW}${message}${NC} "# 如果提供了进程PID,监控进程状态if [ -n "$process_pid" ]; thenwhile kill -0 $process_pid 2>/dev/null; doprintf "\b${CYAN}%s${NC}" "${spinner_chars:spin_i++%${#spinner_chars}:1}"sleep $delaydoneelse# 简单的固定时间动画for i in {1..30}; doprintf "\b${CYAN}%s${NC}" "${spinner_chars:spin_i++%${#spinner_chars}:1}"sleep $delaydonefiecho -e "\b${GREEN}${NC}"
}# 计时器函数
start_timer() {START_TIME=$(date +%s)
}end_timer() {END_TIME=$(date +%s)DURATION=$((END_TIME - START_TIME))local hours=$((DURATION / 3600))local minutes=$(((DURATION % 3600) / 60))local seconds=$((DURATION % 60))if [ $hours -gt 0 ]; thenecho "${hours}小时${minutes}${seconds}秒"elif [ $minutes -gt 0 ]; thenecho "${minutes}${seconds}秒"elseecho "${seconds}秒"fi
}# 检查MySQL连接
check_mysql_connection() {print_color $BLUE "🔍 检查MySQL连接状态..."if mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" -e "SELECT 1;" >/dev/null 2>&1; thenprint_color $GREEN "✅ MySQL连接成功"print_color $CYAN "   连接信息: ${MYSQL_USER}@${MYSQL_HOST}:${MYSQL_PORT}"return 0elseprint_color $RED "❌ MySQL连接失败,请检查连接配置"print_color $YELLOW "   主机: ${MYSQL_HOST}:${MYSQL_PORT}"print_color $YELLOW "   用户: ${MYSQL_USER}"exit 1fi
}# 创建备份目录
create_backup_dir() {if [ ! -d "$BACKUP_DIR" ]; thenprint_color $YELLOW "📁 创建备份目录: $BACKUP_DIR"mkdir -p "$BACKUP_DIR"fi
}# 清理过期备份
cleanup_old_backups() {print_color $BLUE "🧹 清理 ${RETENTION_DAYS} 天前的备份文件..."local deleted_count=0while IFS= read -r -d '' file; dorm -f "$file"deleted_count=$((deleted_count + 1))print_color $YELLOW "  删除: $(basename "$file")"done < <(find "$BACKUP_DIR" -name "*.sql" -type f -mtime +$RETENTION_DAYS -print0 2>/dev/null)# 清理过期的gz文件while IFS= read -r -d '' file; dorm -f "$file"deleted_count=$((deleted_count + 1))print_color $YELLOW "  删除: $(basename "$file")"done < <(find "$BACKUP_DIR" -name "*.gz" -type f -mtime +$RETENTION_DAYS -print0 2>/dev/null)if [ $deleted_count -eq 0 ]; thenprint_color $GREEN "✅ 没有需要清理的过期备份文件"elseprint_color $GREEN "✅ 已清理 ${deleted_count} 个过期备份文件"fi
}# 压缩备份文件
compress_backup() {local sql_file=$1local gz_file="${sql_file}.gz"print_color $BLUE "📦 压缩备份文件..."if command -v gzip >/dev/null 2>&1; thenif gzip "$sql_file"; thenlocal size=$(du -h "$gz_file" | cut -f1)print_color $GREEN "✅ 压缩完成!"print_color $GREEN "   压缩文件: $(basename "$gz_file")"print_color $GREEN "   文件大小: ${size}"echo "$gz_file"elseprint_color $RED "❌ 压缩失败"return 1fielseprint_color $YELLOW "⚠️  系统未安装gzip命令,跳过压缩"echo "$sql_file"fi
}# 获取所有数据库列表(排除系统数据库)
get_all_databases() {mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" -e "SHOW DATABASES;" 2>/dev/null | grep -Ev "^(Database|information_schema|performance_schema|mysql|sys)$"
}# 全量备份
full_backup() {# 备份前先执行清理print_color $BLUE "🧹 备份前清理过期文件..."cleanup_old_backupslocal timestamp=$(date +"%Y%m%d_%H%M%S")local backup_file="${BACKUP_DIR}/full_backup_${timestamp}.sql"print_color $BLUE "🚀 开始全量备份..."print_color $CYAN "   备份文件: $(basename "$backup_file")"# 开始计时start_timer# 后台执行备份命令mysqldump -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" --all-databases $MYSQLDUMP_OPTIONS > "$backup_file" 2>/dev/null &local backup_pid=$!# 显示进度条show_progress "正在执行全量备份" $backup_pid# 等待备份完成并检查结果wait $backup_pidlocal backup_result=$?# 结束计时local elapsed_time=$(end_timer)if [ $backup_result -eq 0 ] && [ -s "$backup_file" ]; thenprint_color $GREEN "✅ 全量备份完成!耗时: ${elapsed_time}"# 压缩备份文件local final_file=$(compress_backup "$backup_file")if [ $? -eq 0 ]; thenprint_color $GREEN "   保存路径: ${final_file}"elseprint_color $GREEN "   保存路径: ${backup_file}"fielseprint_color $RED "❌ 全量备份失败,耗时: ${elapsed_time}"rm -f "$backup_file"return 1fi
}# 部分库备份(排除预设的数据库)
partial_backup() {# 检查是否配置了排除数据库if [ -z "$EXCLUDE_DATABASES" ]; thenprint_color $RED "❌ 未配置排除数据库列表"print_color $YELLOW "   请在脚本顶部的 EXCLUDE_DATABASES 变量中配置要排除的数据库"print_color $YELLOW "   示例: EXCLUDE_DATABASES=\"test_db,log_db,temp_db\""return 1fiprint_color $CYAN "📋 配置的排除数据库: $EXCLUDE_DATABASES"# 将逗号分隔的字符串转换为数组IFS=',' read -ra exclude_array <<< "$EXCLUDE_DATABASES"# 获取所有数据库并排除指定的local all_dbs=$(get_all_databases)local backup_dbs=""if [ -z "$all_dbs" ]; thenprint_color $RED "❌ 未找到任何用户数据库"return 1fiprint_color $BLUE "📊 分析数据库列表..."print_color $CYAN "   发现用户数据库: $(echo $all_dbs | tr '\n' ' ')"# 处理排除逻辑local excluded_dbs=""for db in $all_dbs; dolocal skip=falsefor exclude_db in "${exclude_array[@]}"; do# 去除可能的空格和特殊字符exclude_db=$(echo "$exclude_db" | xargs | tr -d '\r\n')if [ "$db" = "$exclude_db" ]; thenskip=trueexcluded_dbs="$excluded_dbs $db"breakfidoneif [ "$skip" = false ]; thenbackup_dbs="$backup_dbs $db"fidone# 显示处理结果if [ -n "$excluded_dbs" ]; thenprint_color $YELLOW "   已排除数据库:$excluded_dbs"fiprint_color $GREEN "   将备份数据库:$backup_dbs"if [ -z "$backup_dbs" ]; thenprint_color $RED "❌ 排除后没有需要备份的数据库"return 1fiecho ""echo -n -e "${YELLOW}确认执行备份?(y/N): ${NC}"read -r confirmif [[ ! "$confirm" =~ ^[Yy]$ ]]; thenprint_color $YELLOW "⏹️  备份已取消"return 0fi# 备份前先执行清理print_color $BLUE "🧹 备份前清理过期文件..."cleanup_old_backupslocal timestamp=$(date +"%Y%m%d_%H%M%S")local backup_file="${BACKUP_DIR}/partial_backup_${timestamp}.sql"print_color $BLUE "🚀 开始部分库备份..."print_color $CYAN "   备份文件: $(basename "$backup_file")"# 开始计时start_timer# 后台执行备份命令mysqldump -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" --databases $backup_dbs $MYSQLDUMP_OPTIONS > "$backup_file" 2>/dev/null &local backup_pid=$!# 显示进度条show_progress "正在执行部分库备份" $backup_pid# 等待备份完成并检查结果wait $backup_pidlocal backup_result=$?# 结束计时local elapsed_time=$(end_timer)if [ $backup_result -eq 0 ] && [ -s "$backup_file" ]; thenprint_color $GREEN "✅ 部分库备份完成!耗时: ${elapsed_time}"# 压缩备份文件local final_file=$(compress_backup "$backup_file")if [ $? -eq 0 ]; thenprint_color $GREEN "   保存路径: ${final_file}"elseprint_color $GREEN "   保存路径: ${backup_file}"fielseprint_color $RED "❌ 部分库备份失败,耗时: ${elapsed_time}"rm -f "$backup_file"return 1fi
}# 列出备份文件
list_backups() {print_color $BLUE "📋 可用的备份文件:"echo ""local backup_files=($(find "$BACKUP_DIR" \( -name "*.sql" -o -name "*.gz" \) -type f -printf "%T@ %p\n" 2>/dev/null | sort -rn | cut -d' ' -f2-))if [ ${#backup_files[@]} -eq 0 ]; thenprint_color $YELLOW "⚠️  没有找到备份文件"return 1filocal index=1for file in "${backup_files[@]}"; dolocal filename=$(basename "$file")local size=$(du -h "$file" 2>/dev/null | cut -f1)local date=$(date -r "$file" "+%Y-%m-%d %H:%M:%S" 2>/dev/null)printf "${CYAN}%2d.${NC} %-40s ${GREEN}%8s${NC} ${YELLOW}%s${NC}\n" "$index" "$filename" "$size" "$date"index=$((index + 1))donereturn 0
}# 恢复备份
restore_backup() {if ! list_backups; thenreturn 1fiecho ""echo -n -e "${YELLOW}请选择要恢复的备份文件编号: ${NC}"read -r selectionif ! [[ "$selection" =~ ^[0-9]+$ ]]; thenprint_color $RED "❌ 请输入有效的数字"return 1filocal backup_files=($(find "$BACKUP_DIR" \( -name "*.sql" -o -name "*.gz" \) -type f -printf "%T@ %p\n" 2>/dev/null | sort -rn | cut -d' ' -f2-))local selected_index=$((selection - 1))if [ $selected_index -lt 0 ] || [ $selected_index -ge ${#backup_files[@]} ]; thenprint_color $RED "❌ 选择的编号超出范围"return 1filocal backup_file="${backup_files[$selected_index]}"local filename=$(basename "$backup_file")print_color $YELLOW "⚠️  警告:恢复操作将覆盖现有数据库!"print_color $CYAN "选择的备份文件: $filename"echo -n -e "${RED}确认执行恢复操作?(y/N): ${NC}"read -r confirmif [[ ! "$confirm" =~ ^[Yy]$ ]]; thenprint_color $YELLOW "⏹️  恢复已取消"return 0fiprint_color $BLUE "🔄 开始恢复数据库..."print_color $CYAN "   恢复文件: $filename"show_progress 5 "正在执行数据库恢复"# 如果是gz文件,先解压local actual_file="$backup_file"if [[ "$backup_file" == *.gz ]]; thenprint_color $BLUE "📦 解压备份文件..."local temp_sql="${backup_file%.*}"if gunzip -c "$backup_file" > "$temp_sql"; thenactual_file="$temp_sql"elseprint_color $RED "❌ 解压失败"return 1fifiif mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" < "$actual_file" 2>/dev/null; thenprint_color $GREEN "✅ 数据库恢复完成!"# 如果是临时解压的文件,删除它if [[ "$backup_file" == *.gz ]] && [ "$actual_file" != "$backup_file" ]; thenrm -f "$actual_file"fielseprint_color $RED "❌ 数据库恢复失败"# 如果是临时解压的文件,删除它if [[ "$backup_file" == *.gz ]] && [ "$actual_file" != "$backup_file" ]; thenrm -f "$actual_file"fireturn 1fi
}# 显示帮助信息
show_help() {print_color $CYAN "用法:"print_color $WHITE "  $0                    # 交互式模式"print_color $WHITE "  $0 [选项]             # 命令行模式"echo ""print_color $CYAN "选项:"print_color $WHITE "  1                     # 全量备份"print_color $WHITE "  2                     # 部分库备份(排除指定数据库)"print_color $WHITE "  3                     # 恢复备份"print_color $WHITE "  4                     # 查看备份文件"print_color $WHITE "  5                     # 退出"print_color $WHITE "  -h, --help           # 显示此帮助信息"echo ""print_color $CYAN "示例:"print_color $WHITE "  $0 1                 # 直接执行全量备份"print_color $WHITE "  $0 2                 # 直接执行部分库备份"print_color $WHITE "  $0 4                 # 查看备份文件列表"echo ""
}# 显示状态栏
show_status_bar() {echo ""draw_line "─" "$BLUE"printf "${CYAN}状态: ${GREEN}✅ 已连接${NC}"printf "${CYAN} | 备份目录: ${YELLOW}${BACKUP_DIR}${NC}"printf "${CYAN} | 保留天数: ${YELLOW}${RETENTION_DAYS}${NC}\n"draw_line "─" "$BLUE"
}# 显示菜单选项
show_menu_item() {local num=$1local icon=$2local text=$3local desc=$4# 计算总宽度为50个字符,确保在边框内对齐printf "  ${WHITE}[${CYAN}%s${WHITE}]${NC} %s ${WHITE}%-16s${NC} ${YELLOW}%-20s${NC}" "$num" "$icon" "$text" "$desc"
}# 全屏显示菜单
show_menu() {echo ""echo ""center_text "📋 主菜单 - 请选择操作" "$BLUE"echo ""echo ""# 创建菜单框 - 使用固定宽度来确保对齐local menu_width=56local menu_start=$(( (TERM_COLS - menu_width) / 2 ))# 顶部边框printf "%*s${CYAN}┌" $menu_start ""for ((i=1; i<=menu_width-2; i++)); do printf "─"; doneprintf "┐${NC}\n"# 空行printf "%*s${CYAN}│" $menu_start ""printf "%*s${CYAN}${NC}\n" $((menu_width-1)) ""# 菜单项printf "%*s${CYAN}${NC}" $menu_start ""show_menu_item "1" "🗃️ " "全量备份" "备份所有数据库"printf "${CYAN}${NC}\n"printf "%*s${CYAN}${NC}" $menu_start ""printf "%*s${CYAN}${NC}\n" $((menu_width-1)) ""printf "%*s${CYAN}${NC}" $menu_start ""show_menu_item "2" "📦" "部分库备份" "排除指定数据库后备份"printf "${CYAN}${NC}\n"printf "%*s${CYAN}${NC}" $menu_start ""printf "%*s${CYAN}${NC}\n" $((menu_width-1)) ""printf "%*s${CYAN}${NC}" $menu_start ""show_menu_item "3" "🔄" "恢复备份" "从备份文件恢复数据库"printf "${CYAN}${NC}\n"printf "%*s${CYAN}${NC}" $menu_start ""printf "%*s${CYAN}${NC}\n" $((menu_width-1)) ""printf "%*s${CYAN}${NC}" $menu_start ""show_menu_item "4" "📋" "查看备份" "列出所有备份文件"printf "${CYAN}${NC}\n"printf "%*s${CYAN}${NC}" $menu_start ""printf "%*s${CYAN}${NC}\n" $((menu_width-1)) ""printf "%*s${CYAN}${NC}" $menu_start ""show_menu_item "5" "🚪" "退出程序" "安全退出备份工具"printf "${CYAN}${NC}\n"# 空行printf "%*s${CYAN}│" $menu_start ""printf "%*s${CYAN}${NC}\n" $((menu_width-1)) ""# 底部边框printf "%*s${CYAN}└" $menu_start ""for ((i=1; i<=menu_width-2; i++)); do printf "─"; doneprintf "┘${NC}\n"echo ""show_status_barecho ""
}# 执行指定的操作
execute_operation() {local choice=$1case $choice in1)print_color $BLUE "🚀 执行全量备份..."full_backup;;2)print_color $BLUE "📦 执行部分库备份..."partial_backup;;3)print_color $BLUE "🔄 执行备份恢复..."restore_backup;;4)print_color $BLUE "📋 查看备份文件..."list_backups;;5)print_color $GREEN "👋 感谢使用MySQL备份恢复工具!"exit 0;;*)print_color $RED "❌ 无效选择: $choice"print_color $YELLOW "请使用 1-5 之间的数字,或运行 $0 --help 查看帮助"exit 1;;esac
}# 显示输入提示
show_input_prompt() {echo ""center_text "请输入您的选择 [1-5]" "$YELLOW"echo ""printf "%*s${CYAN}${NC}" $(( (TERM_COLS - 10) / 2 )) ""
}# 显示操作结果页面
show_result_page() {local title="$1"local status="$2"clear_screenget_terminal_sizeecho ""draw_border "$title"echo ""if [ "$status" = "success" ]; thencenter_text "✅ 操作完成" "$GREEN"elsecenter_text "❌ 操作失败" "$RED"fiecho ""echo ""center_text "按任意键返回主菜单..." "$CYAN"
}# 交互式模式
interactive_mode() {while true; doclear_screenprint_titleshow_menushow_input_promptread -r choicecase "$choice" in1|2|3|4|5)clear_screenprint_titleexecute_operation "$choice"if [ "$choice" != "5" ]; thenif [ "$choice" != "4" ]; thenecho ""echo ""center_text "操作完成,按任意键返回主菜单..." "$CYAN"read -relseecho ""echo ""center_text "按任意键返回主菜单..." "$CYAN"read -rfifi;;*)clear_screenprint_titleecho ""center_text "❌ 无效选择,请输入 1-5 之间的数字" "$RED"echo ""center_text "按任意键返回主菜单..." "$CYAN"read -r;;esacdone
}# 主函数
main() {# 处理命令行参数if [ $# -gt 0 ]; thencase "$1" in-h|--help)print_titleshow_helpexit 0;;1|2|3|4|5)# 命令行模式 - 直接执行指定操作print_title# 初始化检查check_mysql_connectioncreate_backup_dir# 执行指定操作execute_operation "$1"exit 0;;*)print_color $RED "❌ 无效参数: $1"echo ""show_helpexit 1;;esacfi# 交互式模式# 检查是否为root用户或有sudo权限if [ "$EUID" -ne 0 ] && ! sudo -n true 2>/dev/null; thenprint_color $YELLOW "⚠️  建议使用root权限运行此脚本"fiprint_title# 初始化检查check_mysql_connectioncreate_backup_dir# 进入交互式模式interactive_mode
}# 信号处理
trap 'echo -e "\n${YELLOW}👋 程序已中断退出${NC}"; exit 1' INT TERM# 运行主程序
main "$@"
http://www.lryc.cn/news/613067.html

相关文章:

  • Python面试题及详细答案150道(16-30) -- 数据结构篇
  • 分布式微服务--GateWay(过滤器及使用Gateway注意点)
  • 告别YAML,在SpringBoot中用数据库配置替代配置文件
  • word生成问题总结
  • 【遥感图像入门】近三年遥感图像建筑物细粒度分类技术一览
  • Day116 若依融合mqtt
  • 界面组件DevExpress WPF中文教程:网格视图数据布局 - 紧凑模式
  • 音视频时间戳获取与同步原理详解
  • 【Docker】RustDesk远程控制-私有化部署开源版本
  • 生成式AI的“幽灵漏洞”:法律如何为技术的阴影划界
  • PCIe Base Specification解析(八)
  • 从配置到远程访问:如何用群晖NAS FTP+ Cpolar搭建稳定文件传输通道
  • 深入解析Three.js中的BufferAttribute:源码与实现机制
  • Linux下动态库链接的详细过程
  • C++位图(Bitmap)与布隆过滤器(Bloom Filter)详解及海量数据处理应用
  • vue3父组件把一个对象整体传入子组件,还是把一个对象的多个属性分成多个参数传入
  • C#中统计某个字符出现次数的最简单方法
  • Git `cherry-pick` 工具汇总
  • Numpy科学计算与数据分析:Numpy线性代数基础与实践
  • 第一个vue应用
  • 【Kubernetes】部署 kube-bench 实现 K8s 最佳实践
  • LeetCode 分类刷题:125. 验证回文串
  • LongVie突破超长视频生成极限:1分钟电影级丝滑视频,双模态控制告别卡顿退化
  • Postman接口测试入门
  • ESXI7.0添加标准交换机过程
  • Python 位置参数(positional arguments)
  • 大文件断点续传(vue+springboot+mysql)
  • 8.结构健康监测选自动化:实时数据 + 智能分析,远超人工
  • Python 基础详解:变量(Variables)—— 程序的“记忆单元”
  • Numpy科学计算与数据分析:Numpy数据分析基础之统计函数应用