mirror of
https://github.com/m1ngsama/automa.git
synced 2025-12-24 10:51:20 +00:00
## 重构内容 ### 新增自动化脚本系统 (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配置无变化
339 lines
7.9 KiB
Bash
Executable file
339 lines
7.9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Minecraft 自动化工具 - 通用工具库
|
|
# 提供日志、环境检查、Docker操作等通用函数
|
|
|
|
# ============================================
|
|
# 颜色定义
|
|
# ============================================
|
|
readonly RED='\033[0;31m'
|
|
readonly GREEN='\033[0;32m'
|
|
readonly YELLOW='\033[1;33m'
|
|
readonly BLUE='\033[0;34m'
|
|
readonly CYAN='\033[0;36m'
|
|
readonly NC='\033[0m' # No Color
|
|
|
|
# ============================================
|
|
# 全局变量
|
|
# ============================================
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
LOG_DIR="$PROJECT_ROOT/logs"
|
|
LOG_FILE="$LOG_DIR/automation-$(date +%Y%m%d).log"
|
|
|
|
# 确保日志目录存在
|
|
mkdir -p "$LOG_DIR"
|
|
|
|
# ============================================
|
|
# 日志函数
|
|
# ============================================
|
|
|
|
# 初始化日志文件
|
|
init_log() {
|
|
local title="${1:-Minecraft 自动化任务}"
|
|
{
|
|
echo "=========================================="
|
|
echo "$title"
|
|
echo "开始时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
echo "工作目录: $(pwd)"
|
|
echo "用户: $(whoami)"
|
|
echo "=========================================="
|
|
echo ""
|
|
} >>"$LOG_FILE"
|
|
}
|
|
|
|
# 记录信息
|
|
log_info() {
|
|
local msg="$1"
|
|
local timestamp=$(date '+%H:%M:%S')
|
|
echo -e "${BLUE}[INFO]${NC} ${timestamp} $msg"
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $msg" >>"$LOG_FILE"
|
|
}
|
|
|
|
# 记录成功
|
|
log_success() {
|
|
local msg="$1"
|
|
local timestamp=$(date '+%H:%M:%S')
|
|
echo -e "${GREEN}[✓]${NC} ${timestamp} $msg"
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $msg" >>"$LOG_FILE"
|
|
}
|
|
|
|
# 记录警告
|
|
log_warning() {
|
|
local msg="$1"
|
|
local timestamp=$(date '+%H:%M:%S')
|
|
echo -e "${YELLOW}[⚠]${NC} ${timestamp} $msg"
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARNING] $msg" >>"$LOG_FILE"
|
|
}
|
|
|
|
# 记录错误
|
|
log_error() {
|
|
local msg="$1"
|
|
local timestamp=$(date '+%H:%M:%S')
|
|
echo -e "${RED}[✗]${NC} ${timestamp} $msg"
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $msg" >>"$LOG_FILE"
|
|
}
|
|
|
|
# 记录命令执行
|
|
log_command() {
|
|
local cmd="$1"
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [COMMAND] $cmd" >>"$LOG_FILE"
|
|
}
|
|
|
|
# 记录分隔线
|
|
log_separator() {
|
|
echo "" | tee -a "$LOG_FILE"
|
|
echo "==========================================">>"$LOG_FILE"
|
|
echo "" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
# 显示日志位置
|
|
show_log_file() {
|
|
log_info "详细日志: $LOG_FILE"
|
|
}
|
|
|
|
# ============================================
|
|
# 环境检查函数
|
|
# ============================================
|
|
|
|
# 检查命令是否存在
|
|
check_command() {
|
|
local cmd="$1"
|
|
if ! command -v "$cmd" &>/dev/null; then
|
|
log_error "未找到命令: $cmd"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# 检查Docker环境
|
|
check_docker() {
|
|
log_info "检查 Docker 环境..."
|
|
|
|
if ! check_command docker; then
|
|
log_error "Docker 未安装。请访问: https://docs.docker.com/get-docker/"
|
|
return 1
|
|
fi
|
|
|
|
if ! docker info &>/dev/null; then
|
|
log_error "Docker 服务未运行"
|
|
return 1
|
|
fi
|
|
|
|
if ! command -v docker compose &>/dev/null && ! command -v docker-compose &>/dev/null; then
|
|
log_error "Docker Compose 未安装"
|
|
return 1
|
|
fi
|
|
|
|
log_success "Docker 环境正常"
|
|
return 0
|
|
}
|
|
|
|
# 检查文件是否存在
|
|
check_file() {
|
|
local file="$1"
|
|
local desc="${2:-文件}"
|
|
|
|
if [[ ! -f "$file" ]]; then
|
|
log_error "$desc 不存在: $file"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# 检查目录是否存在
|
|
check_dir() {
|
|
local dir="$1"
|
|
local desc="${2:-目录}"
|
|
|
|
if [[ ! -d "$dir" ]]; then
|
|
log_error "$desc 不存在: $dir"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# ============================================
|
|
# Docker操作函数
|
|
# ============================================
|
|
|
|
# 获取Docker Compose命令
|
|
get_docker_compose_cmd() {
|
|
if command -v docker &>/dev/null && docker compose version &>/dev/null; then
|
|
echo "docker compose"
|
|
elif command -v docker-compose &>/dev/null; then
|
|
echo "docker-compose"
|
|
else
|
|
log_error "未找到 Docker Compose"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# 检查容器状态
|
|
check_container_status() {
|
|
local container_name="${1:-mc-fabric-1.21.1}"
|
|
|
|
if docker ps --format '{{.Names}}' | grep -q "^${container_name}$"; then
|
|
echo "running"
|
|
return 0
|
|
elif docker ps -a --format '{{.Names}}' | grep -q "^${container_name}$"; then
|
|
echo "stopped"
|
|
return 1
|
|
else
|
|
echo "not_found"
|
|
return 2
|
|
fi
|
|
}
|
|
|
|
# 等待容器启动
|
|
wait_for_container() {
|
|
local container_name="${1:-mc-fabric-1.21.1}"
|
|
local timeout="${2:-60}"
|
|
local elapsed=0
|
|
|
|
log_info "等待容器启动: $container_name"
|
|
|
|
while [[ $elapsed -lt $timeout ]]; do
|
|
if docker ps --format '{{.Names}}' | grep -q "^${container_name}$"; then
|
|
log_success "容器已启动"
|
|
return 0
|
|
fi
|
|
sleep 2
|
|
((elapsed += 2))
|
|
echo -n "."
|
|
done
|
|
|
|
echo ""
|
|
log_error "容器启动超时"
|
|
return 1
|
|
}
|
|
|
|
# 执行Docker Compose命令
|
|
docker_compose_exec() {
|
|
local cmd="$1"
|
|
shift
|
|
local compose_cmd=$(get_docker_compose_cmd)
|
|
|
|
if [[ -z "$compose_cmd" ]]; then
|
|
return 1
|
|
fi
|
|
|
|
log_command "$compose_cmd $cmd $*"
|
|
cd "$PROJECT_ROOT" && $compose_cmd $cmd "$@"
|
|
}
|
|
|
|
# ============================================
|
|
# 文件操作函数
|
|
# ============================================
|
|
|
|
# 创建备份
|
|
create_backup() {
|
|
local source="$1"
|
|
local backup_dir="${2:-$PROJECT_ROOT/backups}"
|
|
local name=$(basename "$source")
|
|
local timestamp=$(date +%Y%m%d-%H%M%S)
|
|
local backup_file="$backup_dir/${name}-${timestamp}.tar.gz"
|
|
|
|
mkdir -p "$backup_dir"
|
|
|
|
log_info "创建备份: $name"
|
|
|
|
if [[ -d "$source" ]]; then
|
|
if tar -czf "$backup_file" -C "$(dirname "$source")" "$name" 2>/dev/null; then
|
|
local size=$(du -h "$backup_file" | cut -f1)
|
|
log_success "备份完成: $(basename "$backup_file") ($size)"
|
|
echo "$backup_file"
|
|
return 0
|
|
fi
|
|
elif [[ -f "$source" ]]; then
|
|
if cp "$source" "$backup_file"; then
|
|
log_success "备份完成: $(basename "$backup_file")"
|
|
echo "$backup_file"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
log_error "备份失败: $source"
|
|
return 1
|
|
}
|
|
|
|
# 清理旧备份
|
|
cleanup_old_backups() {
|
|
local backup_dir="$1"
|
|
local keep_count="${2:-5}"
|
|
|
|
if [[ ! -d "$backup_dir" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
log_info "清理旧备份(保留最近 $keep_count 个)"
|
|
|
|
local backup_count=$(find "$backup_dir" -name "*.tar.gz" | wc -l)
|
|
|
|
if [[ $backup_count -le $keep_count ]]; then
|
|
log_info "当前备份数: $backup_count,无需清理"
|
|
return 0
|
|
fi
|
|
|
|
find "$backup_dir" -name "*.tar.gz" -type f -printf '%T@ %p\n' | \
|
|
sort -rn | \
|
|
tail -n +$((keep_count + 1)) | \
|
|
cut -d' ' -f2- | \
|
|
while read -r file; do
|
|
rm -f "$file"
|
|
log_info "删除旧备份: $(basename "$file")"
|
|
done
|
|
|
|
log_success "备份清理完成"
|
|
}
|
|
|
|
# ============================================
|
|
# 网络检查函数
|
|
# ============================================
|
|
|
|
# 检查网络连接
|
|
check_network() {
|
|
local url="${1:-https://api.modrinth.com/v2/project/fabric-api}"
|
|
|
|
if curl -s --connect-timeout 5 "$url" >/dev/null; then
|
|
return 0
|
|
else
|
|
log_warning "网络连接失败: $url"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# ============================================
|
|
# 系统信息函数
|
|
# ============================================
|
|
|
|
# 记录系统信息
|
|
log_system_info() {
|
|
{
|
|
echo "=== 系统信息 ==="
|
|
echo "主机: $(hostname)"
|
|
echo "系统: $(uname -s) $(uname -r)"
|
|
echo "架构: $(uname -m)"
|
|
|
|
if command -v docker &>/dev/null; then
|
|
echo "Docker: $(docker --version 2>/dev/null || echo '未安装')"
|
|
fi
|
|
|
|
if command -v free &>/dev/null; then
|
|
echo "内存: $(free -h | grep Mem: | awk '{print $3 "/" $2}')"
|
|
fi
|
|
|
|
echo "磁盘: $(df -h "$PROJECT_ROOT" | tail -1 | awk '{print $3 "/" $2 " (已用 " $5 ")"}')"
|
|
echo "===================="
|
|
} >>"$LOG_FILE"
|
|
}
|
|
|
|
# ============================================
|
|
# 主函数
|
|
# ============================================
|
|
|
|
# 如果直接执行此脚本
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
echo "这是一个工具库,请通过 source 命令加载"
|
|
echo "用法: source $(basename "$0")"
|
|
exit 1
|
|
fi
|