automa/minecraft/scripts/backup.sh
m1ngsama 0fe7ed79ad refactor: 重构Minecraft服务器自动化管理方案
## 重构内容

### 新增自动化脚本系统 (scripts/)
- utils.sh: 通用工具库(日志、Docker操作、备份、网络检查)
- setup.sh: 环境初始化脚本(目录结构、权限、配置验证)
- mod-manager.sh: Mods管理(Modrinth下载、更新、清理)
- backup.sh: 备份管理(世界/配置/mods备份、恢复、清理)
- monitor.sh: 服务器监控(状态、资源、玩家、日志分析)

### 增强Makefile集成
新增命令:
- minecraft-status: 服务器状态检查
- minecraft-setup: 环境初始化
- minecraft-mods-*: Mods管理命令
- minecraft-backup-*: 备份管理命令

### 完善文档
- 重写README: 详细的使用指南、故障排查、迁移指南
- 新增CHANGELOG: 完整的重构说明和技术细节

## 架构改进

### 整合原有设计
- 继承src/automatic/的日志系统设计
- 改进Modrinth API集成逻辑
- 优化部署流程和备份机制

### 新增优势
- Docker优先的容器化方案
- 模块化脚本设计,职责单一
- Makefile统一管理入口
- 完整的生命周期自动化

## 技术特性

- 完善的错误处理和日志记录
- macOS/Linux跨平台兼容
- 敏感信息安全管理
- 持续监控模式

## 向后兼容

- 保留src/automatic/旧脚本(供参考)
- 配置文件格式完全兼容
- Docker Compose配置无变化
2025-12-09 10:00:00 +08:00

376 lines
7.7 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# Minecraft 服务器备份管理
# 支持世界数据、配置文件、mods 的备份和恢复
set -e
# 加载工具库
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/utils.sh"
# ============================================
# 配置变量
# ============================================
readonly PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
readonly BACKUP_DIR="$PROJECT_ROOT/backups"
readonly DATA_DIR="$PROJECT_ROOT/data"
readonly MODS_DIR="$PROJECT_ROOT/mods"
readonly CONFIGS_DIR="$PROJECT_ROOT/configs"
readonly CONTAINER_NAME="mc-fabric-1.21.1"
# ============================================
# 备份函数
# ============================================
# 备份世界数据
backup_world() {
log_info "备份世界数据..."
local world_dir="$DATA_DIR/world"
if [[ ! -d "$world_dir" ]]; then
log_warning "世界数据不存在: $world_dir"
return 1
fi
# 通知服务器保存
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log_info "通知服务器保存世界..."
docker exec "$CONTAINER_NAME" rcon-cli save-all flush 2>/dev/null || true
sleep 3
fi
# 创建备份
local backup_file=$(create_backup "$world_dir" "$BACKUP_DIR/worlds")
if [[ -n "$backup_file" ]]; then
log_success "世界备份完成"
return 0
else
log_error "世界备份失败"
return 1
fi
}
# 备份配置文件
backup_configs() {
log_info "备份配置文件..."
if [[ ! -d "$CONFIGS_DIR" ]]; then
log_warning "配置目录不存在: $CONFIGS_DIR"
return 1
fi
local backup_file=$(create_backup "$CONFIGS_DIR" "$BACKUP_DIR/configs")
if [[ -n "$backup_file" ]]; then
log_success "配置备份完成"
return 0
else
log_error "配置备份失败"
return 1
fi
}
# 备份 mods
backup_mods() {
log_info "备份 Mods..."
if [[ ! -d "$MODS_DIR" || -z "$(ls -A "$MODS_DIR" 2>/dev/null)" ]]; then
log_warning "Mods 目录为空"
return 1
fi
local backup_file=$(create_backup "$MODS_DIR" "$BACKUP_DIR/mods")
if [[ -n "$backup_file" ]]; then
log_success "Mods 备份完成"
return 0
else
log_error "Mods 备份失败"
return 1
fi
}
# 完整备份
backup_all() {
log_info "开始完整备份..."
log_separator
local success=0
local failed=0
# 备份世界
if backup_world; then
((success++))
else
((failed++))
fi
log_separator
# 备份配置
if backup_configs; then
((success++))
else
((failed++))
fi
log_separator
# 备份 mods
if backup_mods; then
((success++))
else
((failed++))
fi
log_separator
log_info "备份完成 - 成功: $success, 失败: $failed"
return $failed
}
# ============================================
# 恢复函数
# ============================================
# 列出可用备份
list_backups() {
local type="${1:-all}"
log_info "可用备份:"
case "$type" in
world | worlds)
list_backup_type "worlds" "世界数据"
;;
config | configs)
list_backup_type "configs" "配置文件"
;;
mods)
list_backup_type "mods" "Mods"
;;
all | *)
list_backup_type "worlds" "世界数据"
list_backup_type "configs" "配置文件"
list_backup_type "mods" "Mods"
;;
esac
}
# 列出特定类型的备份
list_backup_type() {
local subdir="$1"
local name="$2"
local backup_path="$BACKUP_DIR/$subdir"
echo ""
log_info "=== $name ==="
if [[ ! -d "$backup_path" ]]; then
log_warning "无可用备份"
return
fi
local count=0
while IFS= read -r file; do
local filename=$(basename "$file")
local size=$(du -h "$file" | cut -f1)
local date=$(echo "$filename" | grep -oP '\d{8}-\d{6}' || echo "未知")
printf " ${CYAN}${NC} %-60s %8s\n" "$filename" "$size"
((count++))
done < <(find "$backup_path" -name "*.tar.gz" -type f 2>/dev/null | sort -r)
if [[ $count -eq 0 ]]; then
log_warning "无可用备份"
else
log_info "$count 个备份"
fi
}
# 恢复备份
restore_backup() {
local backup_file="$1"
if [[ ! -f "$backup_file" ]]; then
log_error "备份文件不存在: $backup_file"
return 1
fi
log_warning "恢复备份将覆盖现有数据"
log_info "备份文件: $(basename "$backup_file")"
# 确定恢复目标
local target_dir=""
if [[ "$backup_file" =~ /worlds/ ]]; then
target_dir="$DATA_DIR"
elif [[ "$backup_file" =~ /configs/ ]]; then
target_dir=$(dirname "$CONFIGS_DIR")
elif [[ "$backup_file" =~ /mods/ ]]; then
target_dir=$(dirname "$MODS_DIR")
else
log_error "无法确定备份类型"
return 1
fi
log_info "恢复目标: $target_dir"
# 解压备份
if tar -xzf "$backup_file" -C "$target_dir"; then
log_success "备份恢复完成"
return 0
else
log_error "备份恢复失败"
return 1
fi
}
# ============================================
# 清理函数
# ============================================
# 清理旧备份
cleanup_backups() {
local keep="${1:-5}"
log_info "清理旧备份(保留最近 $keep 个)..."
log_separator
cleanup_old_backups "$BACKUP_DIR/worlds" "$keep"
cleanup_old_backups "$BACKUP_DIR/configs" "$keep"
cleanup_old_backups "$BACKUP_DIR/mods" "$keep"
log_success "备份清理完成"
}
# 显示备份统计
show_backup_stats() {
log_info "备份统计信息"
log_separator
local types=("worlds:世界数据" "configs:配置文件" "mods:Mods")
for type_pair in "${types[@]}"; do
local type="${type_pair%%:*}"
local name="${type_pair##*:}"
local backup_path="$BACKUP_DIR/$type"
if [[ -d "$backup_path" ]]; then
local count=$(find "$backup_path" -name "*.tar.gz" 2>/dev/null | wc -l)
local total_size=$(du -sh "$backup_path" 2>/dev/null | cut -f1)
log_info "$name: $count 个备份, 总大小: $total_size"
else
log_info "$name: 无备份"
fi
done
log_separator
if [[ -d "$BACKUP_DIR" ]]; then
local total_size=$(du -sh "$BACKUP_DIR" 2>/dev/null | cut -f1)
log_info "备份总大小: $total_size"
fi
}
# ============================================
# 主函数
# ============================================
show_usage() {
cat <<EOF
Minecraft 服务器备份管理
用法: $(basename "$0") [命令] [选项]
命令:
backup [type] 创建备份
type:
world 仅备份世界数据
config 仅备份配置文件
mods 仅备份 mods
all 完整备份(默认)
list [type] 列出可用备份
restore <file> 恢复指定备份
cleanup [num] 清理旧备份默认保留5个
stats 显示备份统计信息
help 显示此帮助信息
示例:
$(basename "$0") backup all # 完整备份
$(basename "$0") backup world # 仅备份世界
$(basename "$0") list # 列出所有备份
$(basename "$0") cleanup 10 # 保留最近10个备份
备份位置: $BACKUP_DIR
EOF
}
main() {
local command="${1:-help}"
shift || true
# 初始化日志
init_log "Minecraft 备份管理"
log_system_info
case "$command" in
backup)
local type="${1:-all}"
case "$type" in
world | worlds)
backup_world
;;
config | configs)
backup_configs
;;
mods)
backup_mods
;;
all | *)
backup_all
;;
esac
;;
list)
list_backups "${1:-all}"
;;
restore)
local file="$1"
if [[ -z "$file" ]]; then
log_error "请指定备份文件"
exit 1
fi
restore_backup "$file"
;;
cleanup)
cleanup_backups "${1:-5}"
;;
stats)
show_backup_stats
;;
help | --help | -h)
show_usage
;;
*)
log_error "未知命令: $command"
echo ""
show_usage
exit 1
;;
esac
show_log_file
}
# 执行主函数
main "$@"