automa/minecraft/scripts/monitor.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

315 lines
6.9 KiB
Bash
Executable file
Raw Permalink 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 服务器监控脚本
# 监控容器状态、资源使用、玩家在线等信息
set -e
# 加载工具库
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/utils.sh"
# ============================================
# 配置变量
# ============================================
readonly PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
readonly CONTAINER_NAME="mc-fabric-1.21.1"
# ============================================
# 容器状态检查
# ============================================
check_container() {
log_info "检查容器状态..."
local status=$(check_container_status "$CONTAINER_NAME")
case "$status" in
running)
log_success "容器正在运行"
return 0
;;
stopped)
log_warning "容器已停止"
return 1
;;
not_found)
log_error "容器不存在"
return 2
;;
esac
}
# ============================================
# 资源使用监控
# ============================================
show_resource_usage() {
log_info "资源使用情况"
log_separator
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log_warning "容器未运行"
return 1
fi
# 获取容器统计信息
local stats=$(docker stats --no-stream --format "{{.CPUPerc}}|{{.MemUsage}}|{{.NetIO}}|{{.BlockIO}}" "$CONTAINER_NAME")
local cpu=$(echo "$stats" | cut -d'|' -f1)
local mem=$(echo "$stats" | cut -d'|' -f2)
local net=$(echo "$stats" | cut -d'|' -f3)
local disk=$(echo "$stats" | cut -d'|' -f4)
printf "${CYAN}CPU 使用:${NC} %s\n" "$cpu"
printf "${CYAN}内存使用:${NC} %s\n" "$mem"
printf "${CYAN}网络 I/O:${NC} %s\n" "$net"
printf "${CYAN}磁盘 I/O:${NC} %s\n" "$disk"
log_separator
}
# ============================================
# 服务器信息
# ============================================
show_server_info() {
log_info "服务器信息"
log_separator
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log_warning "容器未运行"
return 1
fi
# 容器运行时间
local uptime=$(docker inspect --format='{{.State.StartedAt}}' "$CONTAINER_NAME")
uptime=$(date -j -f "%Y-%m-%dT%H:%M:%S" "${uptime:0:19}" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$uptime")
printf "${CYAN}启动时间:${NC} %s\n" "$uptime"
# 端口映射
local ports=$(docker port "$CONTAINER_NAME" 2>/dev/null | grep "25565" | head -1)
printf "${CYAN}服务端口:${NC} %s\n" "${ports:-未映射}"
# 容器 IP
local container_ip=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$CONTAINER_NAME")
printf "${CYAN}容器 IP:${NC} %s\n" "${container_ip:-未知}"
log_separator
}
# ============================================
# 玩家信息
# ============================================
show_players() {
log_info "在线玩家"
log_separator
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log_warning "容器未运行"
return 1
fi
# 尝试使用 rcon 获取玩家列表
local player_list=$(docker exec "$CONTAINER_NAME" rcon-cli list 2>/dev/null || echo "无法获取玩家信息")
if [[ "$player_list" =~ "There are" ]]; then
echo "$player_list"
else
log_warning "无法获取玩家信息(可能需要配置 RCON"
fi
log_separator
}
# ============================================
# 日志监控
# ============================================
show_recent_logs() {
local lines="${1:-20}"
log_info "最近 $lines 行日志"
log_separator
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log_warning "容器未运行"
return 1
fi
docker logs --tail "$lines" "$CONTAINER_NAME" 2>&1
log_separator
}
# 监控日志中的错误
check_errors() {
log_info "检查错误日志"
log_separator
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log_warning "容器未运行"
return 1
fi
local error_count=$(docker logs --tail 1000 "$CONTAINER_NAME" 2>&1 | grep -ic "error" || echo "0")
local warn_count=$(docker logs --tail 1000 "$CONTAINER_NAME" 2>&1 | grep -ic "warn" || echo "0")
if [[ $error_count -gt 0 ]]; then
log_warning "发现 $error_count 个错误"
else
log_success "无错误日志"
fi
if [[ $warn_count -gt 0 ]]; then
log_warning "发现 $warn_count 个警告"
fi
log_separator
}
# ============================================
# 完整状态报告
# ============================================
show_full_status() {
log_info "=== Minecraft 服务器完整状态 ==="
log_separator
# 检查容器
if ! check_container; then
return 1
fi
log_separator
# 服务器信息
show_server_info
# 资源使用
show_resource_usage
# 玩家信息
show_players
# 错误检查
check_errors
log_success "状态检查完成"
}
# ============================================
# 持续监控
# ============================================
watch_mode() {
local interval="${1:-5}"
log_info "开始持续监控(每 ${interval}s 刷新Ctrl+C 退出)"
log_separator
while true; do
clear
echo "=== Minecraft 服务器监控 ==="
echo "刷新时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""
show_server_info 2>/dev/null || true
show_resource_usage 2>/dev/null || true
show_players 2>/dev/null || true
sleep "$interval"
done
}
# ============================================
# 主函数
# ============================================
show_usage() {
cat <<EOF
Minecraft 服务器监控工具
用法: $(basename "$0") [命令] [选项]
命令:
status 显示完整状态(默认)
container 检查容器状态
resources 显示资源使用情况
server 显示服务器信息
players 显示在线玩家
logs [n] 显示最近 n 行日志默认20行
errors 检查错误日志
watch [sec] 持续监控模式默认每5秒刷新
help 显示此帮助信息
示例:
$(basename "$0") # 显示完整状态
$(basename "$0") resources # 仅显示资源使用
$(basename "$0") logs 50 # 显示最近50行日志
$(basename "$0") watch 10 # 每10秒刷新一次
容器名称: $CONTAINER_NAME
EOF
}
main() {
local command="${1:-status}"
shift || true
# 初始化日志
init_log "Minecraft 服务器监控"
case "$command" in
status)
show_full_status
;;
container)
check_container
;;
resources | res)
show_resource_usage
;;
server | info)
show_server_info
;;
players | player)
show_players
;;
logs | log)
show_recent_logs "${1:-20}"
;;
errors | error)
check_errors
;;
watch)
watch_mode "${1:-5}"
;;
help | --help | -h)
show_usage
;;
*)
log_error "未知命令: $command"
echo ""
show_usage
exit 1
;;
esac
if [[ "$command" != "watch" ]]; then
show_log_file
fi
}
# 执行主函数
main "$@"