restore_verify.sh•6.59 kB
#!/bin/bash
# MemOS备份恢复验证脚本
# 用于验证备份文件的完整性和可恢复性
set -e
# 配置变量
MEMOS_DIR="/home/qqinshu/视频/MemOS"
BACKUP_BASE_DIR="$MEMOS_DIR/memos_data/backups"
TEST_RESTORE_DIR="/tmp/memos_restore_test"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${BLUE}ℹ️ $1${NC}"
}
log_success() {
echo -e "${GREEN}✅ $1${NC}"
}
log_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
log_error() {
echo -e "${RED}❌ $1${NC}"
}
# 显示帮助信息
show_help() {
echo "MemOS备份恢复验证脚本"
echo ""
echo "用法: $0 [选项] [备份文件]"
echo ""
echo "选项:"
echo " -h, --help 显示此帮助信息"
echo " -l, --list 列出所有可用的备份文件"
echo " -a, --auto 自动选择最新的备份文件进行验证"
echo ""
echo "示例:"
echo " $0 -l # 列出所有备份文件"
echo " $0 -a # 验证最新备份"
echo " $0 memos_backup_20250715_214416.tar.gz # 验证指定备份文件"
}
# 列出所有备份文件
list_backups() {
log_info "可用的备份文件:"
cd "$BACKUP_BASE_DIR"
if ls memos_backup_*.tar.gz 1> /dev/null 2>&1; then
echo ""
ls -lht memos_backup_*.tar.gz | while read -r line; do
echo " $line"
done
echo ""
else
log_warning "未找到任何备份文件"
exit 1
fi
}
# 获取最新的备份文件
get_latest_backup() {
cd "$BACKUP_BASE_DIR"
LATEST_BACKUP=$(ls -t memos_backup_*.tar.gz 2>/dev/null | head -n 1)
if [ -z "$LATEST_BACKUP" ]; then
log_error "未找到任何备份文件"
exit 1
fi
echo "$LATEST_BACKUP"
}
# 验证备份文件完整性
verify_backup_integrity() {
local backup_file="$1"
log_info "验证备份文件完整性: $backup_file"
# 检查文件是否存在
if [ ! -f "$BACKUP_BASE_DIR/$backup_file" ]; then
log_error "备份文件不存在: $backup_file"
exit 1
fi
# 验证tar文件完整性
if tar -tzf "$BACKUP_BASE_DIR/$backup_file" > /dev/null 2>&1; then
log_success "备份文件完整性验证通过"
else
log_error "备份文件损坏或格式错误"
exit 1
fi
# 显示备份文件内容
log_info "备份文件内容:"
tar -tzf "$BACKUP_BASE_DIR/$backup_file" | head -20
local file_count=$(tar -tzf "$BACKUP_BASE_DIR/$backup_file" | wc -l)
log_info "备份文件包含 $file_count 个文件/目录"
}
# 执行恢复测试
perform_restore_test() {
local backup_file="$1"
log_info "执行恢复测试: $backup_file"
# 清理并创建测试目录
rm -rf "$TEST_RESTORE_DIR"
mkdir -p "$TEST_RESTORE_DIR"
# 解压备份文件到测试目录
cd "$TEST_RESTORE_DIR"
tar -xzf "$BACKUP_BASE_DIR/$backup_file"
if [ $? -eq 0 ]; then
log_success "备份文件解压成功"
else
log_error "备份文件解压失败"
exit 1
fi
# 验证解压后的文件结构
local extracted_dir=$(ls -1 | head -n 1)
if [ -d "$extracted_dir" ]; then
log_info "解压后的目录结构:"
tree "$extracted_dir" 2>/dev/null || find "$extracted_dir" -type f | head -10
# 验证关键文件
verify_extracted_files "$extracted_dir"
else
log_error "解压后未找到预期的目录结构"
exit 1
fi
}
# 验证解压后的文件
verify_extracted_files() {
local extracted_dir="$1"
log_info "验证解压后的关键文件..."
# 检查记忆备份文件
if find "$extracted_dir" -name "memories_backup_*.json" | grep -q .; then
log_success "找到记忆备份文件"
# 验证JSON格式
local memory_file=$(find "$extracted_dir" -name "memories_backup_*.json" | head -n 1)
if python3 -m json.tool "$memory_file" > /dev/null 2>&1; then
log_success "记忆备份文件JSON格式正确"
# 显示记忆数量
local memory_count=$(python3 -c "import json; data=json.load(open('$memory_file')); print(len(data))" 2>/dev/null || echo "未知")
log_info "备份包含 $memory_count 条记忆"
else
log_error "记忆备份文件JSON格式错误"
fi
else
log_warning "未找到记忆备份文件"
fi
# 检查配置文件
if [ -d "$extracted_dir/configs" ]; then
log_success "找到配置文件目录"
local config_count=$(find "$extracted_dir/configs" -name "*.json" | wc -l)
log_info "备份包含 $config_count 个配置文件"
else
log_warning "未找到配置文件目录"
fi
# 检查数据目录
if [ -d "$extracted_dir/data" ]; then
log_success "找到数据目录"
local data_size=$(du -sh "$extracted_dir/data" | cut -f1)
log_info "数据目录大小: $data_size"
else
log_warning "未找到数据目录"
fi
}
# 清理测试环境
cleanup_test_env() {
log_info "清理测试环境..."
if [ -d "$TEST_RESTORE_DIR" ]; then
rm -rf "$TEST_RESTORE_DIR"
log_success "测试环境清理完成"
fi
}
# 主函数
main() {
echo "🔍 MemOS备份恢复验证脚本"
echo "========================="
# 解析命令行参数
case "${1:-}" in
-h|--help)
show_help
exit 0
;;
-l|--list)
list_backups
exit 0
;;
-a|--auto)
BACKUP_FILE=$(get_latest_backup)
log_info "自动选择最新备份文件: $BACKUP_FILE"
;;
"")
log_error "请指定备份文件或使用 -a 选项"
echo ""
show_help
exit 1
;;
*)
BACKUP_FILE="$1"
;;
esac
# 执行验证流程
verify_backup_integrity "$BACKUP_FILE"
perform_restore_test "$BACKUP_FILE"
echo ""
log_success "备份恢复验证完成!"
log_info "备份文件 $BACKUP_FILE 可以正常恢复"
# 清理测试环境
cleanup_test_env
}
# 信号处理
trap 'log_error "验证过程被中断"; cleanup_test_env; exit 130' INT TERM
# 运行主函数
main "$@"