官方服务器端下载地址:
https://www.minecraft.net/en-us/download/server/bedrock
Ubuntu 版本 Minecraft 服务端管理脚本:
#!/bin/bash
set -u
# =====================================================================
# 工具名称: mc_ctl.sh
# 功能描述: Minecraft 基岩版 (BDS) 智能运维工具 (环境检测/扫描接管/智能配置/极速更新)
# 适用环境: Linux (Ubuntu/Debian/CentOS/Alibaba Cloud Linux)
# =====================================================================
# 默认全局配置
DEFAULT_SERVICE_NAME="mc"
DEFAULT_SCREEN_NAME="mc"
DEFAULT_SERVER_DIR="$HOME/mc-server"
DEFAULT_BACKUP_DIR="$HOME/mc_backups"
RUN_USER="$USER"
# 颜色定义
C_RED="\033[31m"
C_GREEN="\033[32m"
C_YELLOW="\033[33m"
C_BLUE="\033[34m"
C_CYAN="\033[36m"
C_BOLD="\033[1m"
C_RESET="\033[0m"
# ---------------------------------------------------------
# 1. 硬件环境检测
# ---------------------------------------------------------
detect_hardware() {
echo -e "\n${C_CYAN}${C_BOLD}================ 🖥️ 服务器硬件与网络环境 ================ ${C_RESET}"
# CPU
CPU_MODEL=$(lscpu | grep -i "Model name" | head -n 1 | awk -F: '{print $2}' | sed 's/^[ \t]*//')
[ -z "$CPU_MODEL" ] && CPU_MODEL="Generic CPU"
CPU_CORES=$(nproc)
# 内存 (MB)
TOTAL_MEM_KB=$(grep MemTotal /proc/meminfo | awk '{print $2}')
TOTAL_MEM_MB=$((TOTAL_MEM_KB / 1024))
AVAIL_MEM_KB=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
AVAIL_MEM_MB=$((AVAIL_MEM_KB / 1024))
# 磁盘空间 (根目录)
DISK_AVAIL=$(df -h / | awk 'NR==2 {print $4}')
# IP 地址探测
PUBLIC_IP=$(curl -s --connect-timeout 3 http://ipv4.icanhazip.com || echo "未能检测到公网IP")
echo -e " 🔹 CPU 型号: ${C_YELLOW}${CPU_MODEL}${C_RESET}"
echo -e " 🔹 CPU 核心: ${C_GREEN}${CPU_CORES} 核心${C_RESET}"
echo -e " 🔹 物理内存: ${C_GREEN}${TOTAL_MEM_MB} MB${C_RESET} (可用: ${AVAIL_MEM_MB} MB)"
echo -e " 🔹 磁盘可用: ${C_GREEN}${DISK_AVAIL}${C_RESET}"
echo -e " 🔹 公网地址: ${C_YELLOW}${PUBLIC_IP}${C_RESET}"
echo -e "${C_CYAN}========================================================${C_RESET}\n"
}
# ---------------------------------------------------------
# 2. 依赖检查与补齐
# ---------------------------------------------------------
check_dependencies() {
local missing_pkgs=()
for pkg in curl unzip tar screen rsync; do
if ! command -v "$pkg" &>/dev/null; then
missing_pkgs+=("$pkg")
fi
done
if ! ldconfig -p | grep -q "libcurl\.so\.4" 2>/dev/null; then
missing_pkgs+=("libcurl4")
fi
if [ ${#missing_pkgs[@]} -gt 0 ]; then
echo -e "${C_YELLOW}💡 检测到缺少必要依赖: ${missing_pkgs[*]}${C_RESET}"
read -p "是否自动执行 apt install 安装?(y/N): " choice
if [[ "$choice" =~ ^[Yy]$ ]]; then
sudo apt-get update && sudo apt-get install -y "${missing_pkgs[@]}"
else
echo -e "${C_RED}❌ 缺少依赖,操作终止。${C_RESET}"
exit 1
fi
fi
}
# ---------------------------------------------------------
# 3. 国内高可用版本探测
# ---------------------------------------------------------
get_latest_version() {
echo -e "🔍 正在探测 Minecraft 基岩版最新版本号..."
local ver=""
# 途径 1:阿里云 npmmirror 镜像源
local npm_data
npm_data=$(curl -s --connect-timeout 5 -m 8 "https://registry.npmmirror.com/@minecraft/server" 2>/dev/null || true)
if [ -n "$npm_data" ]; then
ver=$(echo "$npm_data" | grep -o 'beta\.1\.[0-9.]\+-stable' | sed -E 's/beta\.1\.([0-9.]+)-stable/\1/' | sort -V | tail -n 1)
fi
# 途径 2:国内可用 GitHub 代理池
if [ -z "$ver" ]; then
local PROXIES=("https://ghp.ci/" "https://ghproxy.net/" "https://github.moeyy.xyz/")
for p in "${PROXIES[@]}"; do
local res
res=$(curl -s --connect-timeout 4 -m 6 "${p}https://raw.githubusercontent.com/Bedrock-OSS/BDS-Versions/main/versions.json" 2>/dev/null || true)
if [ -n "$res" ]; then
ver=$(echo "$res" | grep -o '"linux": *"[^"]*"' | head -n 1 | cut -d '"' -f 4)
[ -n "$ver" ] && break
fi
done
fi
# 途径 3:微软官方下载页直连
if [ -z "$ver" ]; then
ver=$(curl -s -L --connect-timeout 6 -m 10 \
-H "Accept-Language: zh-CN,zh;q=0.9,en;q=0.8" \
-A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" \
"https://www.minecraft.net/zh-hans/download/server/bedrock" 2>/dev/null | \
grep -o 'https://www.minecraft.net/bedrockdedicatedserver/bin-linux/bedrock-server-[^"]*\.zip' | \
head -n 1 | \
sed -E 's/.*bedrock-server-([0-9.]+)\.zip/\1/')
fi
echo "$ver"
}
# ---------------------------------------------------------
# 4. 根据硬件生成最优 server.properties
# ---------------------------------------------------------
optimize_server_properties() {
local target_file="$1"
local cores="$2"
local mem_mb="$3"
echo -e "⚙️ 正在根据服务器硬件配置 (${cores}核 / ${mem_mb}MB) 调优参数..."
local view_dist=16
local tick_dist=4
local max_threads="$cores"
local max_players=10
if [ "$mem_mb" -le 2048 ] || [ "$cores" -le 1 ]; then
# 1核 / 2G 以内低配机型
view_dist=10
tick_dist=4
max_players=5
max_threads=2
elif [ "$mem_mb" -ge 12000 ] && [ "$cores" -ge 8 ]; then
# 8核 / 16G 以上高配机型
view_dist=24
tick_dist=6
max_players=20
max_threads=0 # 0 代表全核心自适应
fi
# 更新或追加 server.properties 配置
declare -A configs=(
["view-distance"]="$view_dist"
["tick-distance"]="$tick_dist"
["max-threads"]="$max_threads"
["max-players"]="$max_players"
["server-authoritative-movement"]="server-auth"
["player-idle-timeout"]="30"
)
for key in "${!configs[@]}"; do
local val="${configs[$key]}"
if grep -q "^${key}=" "$target_file" 2>/dev/null; then
sed -i "s/^${key}=.*/${key}=${val}/" "$target_file"
else
echo "${key}=${val}" >> "$target_file"
fi
done
echo -e " ✅ 视距(view-distance): ${C_GREEN}${view_dist}${C_RESET} | 模拟距离(tick-distance): ${C_GREEN}${tick_dist}${C_RESET} | 线程上限: ${C_GREEN}${max_threads}${C_RESET}"
}
# ---------------------------------------------------------
# 5. 生成 systemd 服务文件
# ---------------------------------------------------------
create_systemd_service() {
local s_name="$1"
local scr_name="$2"
local s_dir="$3"
local s_user="$4"
local service_path="/etc/systemd/system/${s_name}.service"
echo -e "👉 正在配置守护服务: ${C_YELLOW}${service_path}${C_RESET} ..."
sudo bash -c "cat <<EOF > $service_path
[Unit]
Description=Minecraft Bedrock Server ($s_name)
After=network.target
[Service]
Type=forking
User=$s_user
WorkingDirectory=$s_dir
ExecStart=/usr/bin/screen -dmS $scr_name /bin/bash -c 'LD_LIBRARY_PATH=. ./bedrock_server'
ExecStop=/usr/bin/screen -S $scr_name -p 0 -X stuff \"\$(printf 'stop\\\r')\"
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF"
sudo systemctl daemon-reload
sudo systemctl enable "$s_name"
}
# ---------------------------------------------------------
# 6. 下载核心包(优先微软 Azure CDN)
# ---------------------------------------------------------
download_server_zip() {
local ver="$1"
local dest_file="$2"
local cdn_url="https://minecraft.azureedge.net/bin-linux/bedrock-server-${ver}.zip"
local off_url="https://www.minecraft.net/bedrockdedicatedserver/bin-linux/bedrock-server-${ver}.zip"
echo "👉 正在下载 Bedrock 服务端 ($ver) ..."
if curl -fL -A "Mozilla/5.0" --connect-timeout 8 -m 120 -o "$dest_file" "$cdn_url"; then
return 0
fi
echo "⚠️ 官方 CDN 波动,尝试直连备用节点..."
if curl -fL -A "Mozilla/5.0" --connect-timeout 8 -m 120 -o "$dest_file" "$off_url"; then
return 0
fi
return 1
}
# ---------------------------------------------------------
# 功能 A:全新一键安装
# ---------------------------------------------------------
action_install() {
echo -e "\n${C_GREEN}${C_BOLD}=== 🚀 开始全新部署 Minecraft 基岩版 ===${C_RESET}"
check_dependencies
detect_hardware
read -p "👉 请输入安装目录 [默认: $DEFAULT_SERVER_DIR]: " INPUT_DIR
SERVER_DIR="${INPUT_DIR:-$DEFAULT_SERVER_DIR}"
read -p "👉 请输入 systemd 服务名 [默认: $DEFAULT_SERVICE_NAME]: " INPUT_SVC
SERVICE_NAME="${INPUT_SVC:-$DEFAULT_SERVICE_NAME}"
SCREEN_NAME="$SERVICE_NAME"
# 版本获取
LATEST_VER=$(get_latest_version)
if [ -n "$LATEST_VER" ]; then
echo -e "💡 成功获取最新版本: ${C_GREEN}${LATEST_VER}${C_RESET}"
read -p "👉 请输入目标版本号 (直接回车使用 $LATEST_VER): " INPUT_VER
TARGET_VER="${INPUT_VER:-$LATEST_VER}"
else
read -p "👉 请手动输入版本号 (例如 1.21.50.07): " TARGET_VER
fi
TMP_ZIP="/tmp/mc_bds_${TARGET_VER}.zip"
mkdir -p "$SERVER_DIR" "$DEFAULT_BACKUP_DIR"
if ! download_server_zip "$TARGET_VER" "$TMP_ZIP"; then
echo -e "${C_RED}❌ 下载失败,请检查网络后重试。${C_RESET}"
rm -f "$TMP_ZIP"
return
fi
echo "👉 正在解压核心程序..."
unzip -q -o "$TMP_ZIP" -d "$SERVER_DIR"
rm -f "$TMP_ZIP"
# 权限
chmod +x "$SERVER_DIR/bedrock_server"
sudo chown -R "$RUN_USER:$RUN_USER" "$SERVER_DIR"
# 硬件自适应优化
optimize_server_properties "$SERVER_DIR/server.properties" "$CPU_CORES" "$TOTAL_MEM_MB"
# 配置 systemd
create_systemd_service "$SERVICE_NAME" "$SCREEN_NAME" "$SERVER_DIR" "$RUN_USER"
echo "👉 正在启动服务..."
sudo systemctl start "$SERVICE_NAME"
sleep 3
if systemctl is-active --quiet "$SERVICE_NAME"; then
echo -e "\n${C_GREEN}🎉 恭喜!服务器已成功安装并运行!${C_RESET}"
echo -e "🔹 默认端口: ${C_YELLOW}19132 (UDP)${C_RESET}"
echo -e "🔹 服务管理: ${C_CYAN}sudo systemctl restart/stop $SERVICE_NAME${C_RESET}"
echo -e "🔹 终端控制: ${C_CYAN}screen -r $SCREEN_NAME${C_RESET} (退出按 Ctrl+A 再按 D)"
else
echo -e "${C_RED}⚠️ 服务未能正常启动,请执行查看原因: sudo journalctl -u $SERVICE_NAME -n 30${C_RESET}"
fi
}
# ---------------------------------------------------------
# 功能 B:全盘扫描现有服务端并接管
# ---------------------------------------------------------
action_scan_and_takeover() {
echo -e "\n${C_YELLOW}${C_BOLD}=== 🔍 扫描现有 Minecraft 服务端 ===${C_RESET}"
echo "正在扫描系统目录 ($HOME, /opt, /srv, /var, /root)..."
local found_dirs=()
while IFS= read -r line; do
found_dirs+=("$(dirname "$line")")
done < <(find "$HOME" /opt /srv /var 2>/dev/null -maxdepth 4 -type f -name "bedrock_server")
if [ ${#found_dirs[@]} -eq 0 ]; then
echo -e "${C_RED}❌ 未能扫描到任何包含 bedrock_server 的目录。${C_RESET}"
return
fi
echo -e "💡 发现以下基岩版服务端目录:"
local i=1
for d in "${found_dirs[@]}"; do
# 检查是否已被 systemd 纳管
local status="未纳管"
if grep -qs "$d" /etc/systemd/system/*.service 2>/dev/null; then
status="${C_GREEN}已纳管${C_RESET}"
fi
echo -e " [$i] $d ($status)"
((i++))
done
read -p "👉 请选择要接管/配置的序号 (输入 0 取消): " choice
if ! [[ "$choice" =~ ^[0-9]+$ ]] || [ "$choice" -le 0 ] || [ "$choice" -gt ${#found_dirs[@]} ]; then
echo "已取消。"
return
fi
local selected_dir="${found_dirs[$((choice-1))]}"
echo -e "已选定目录: ${C_CYAN}$selected_dir${C_RESET}"
read -p "👉 请为该服务指定一个名称 [默认: mc]: " INPUT_SVC
local s_name="${INPUT_SVC:-mc}"
# 1. 修复权限
chmod +x "$selected_dir/bedrock_server"
sudo chown -R "$RUN_USER:$RUN_USER" "$selected_dir"
# 2. 硬件优化
detect_hardware
read -p "👉 是否根据当前硬件重新优化 server.properties 配置?(y/N): " opt_choice
if [[ "$opt_choice" =~ ^[Yy]$ ]]; then
optimize_server_properties "$selected_dir/server.properties" "$CPU_CORES" "$TOTAL_MEM_MB"
fi
# 3. 创建守护
create_systemd_service "$s_name" "$s_name" "$selected_dir" "$RUN_USER"
read -p "👉 是否立即启动该服务?(y/N): " start_choice
if [[ "$start_choice" =~ ^[Yy]$ ]]; then
sudo systemctl start "$s_name"
sleep 2
if systemctl is-active --quiet "$s_name"; then
echo -e "${C_GREEN}✅ 服务 $s_name 已启动并纳管!${C_RESET}"
else
echo -e "${C_RED}⚠️ 启动遇到问题,请查看: sudo journalctl -u $s_name -n 30${C_RESET}"
fi
fi
}
# ---------------------------------------------------------
# 功能 C:无损更新现有服务
# ---------------------------------------------------------
action_update() {
echo -e "\n${C_BLUE}${C_BOLD}=== 🔄 更新现有 Minecraft 服务 ===${C_RESET}"
read -p "👉 请输入服务端所在目录 [默认: $DEFAULT_SERVER_DIR]: " INPUT_DIR
local s_dir="${INPUT_DIR:-$DEFAULT_SERVER_DIR}"
if [ ! -f "$s_dir/bedrock_server" ]; then
echo -e "${C_RED}❌ 目录 $s_dir 下未找到 bedrock_server 程序!${C_RESET}"
return
fi
read -p "👉 请输入 systemd 服务名 [默认: $DEFAULT_SERVICE_NAME]: " INPUT_SVC
local s_name="${INPUT_SVC:-$DEFAULT_SERVICE_NAME}"
local scr_name="$s_name"
local latest_ver
latest_ver=$(get_latest_version)
if [ -n "$latest_ver" ]; then
echo -e "💡 成功获取最新版本: ${C_GREEN}${latest_ver}${C_RESET}"
read -p "👉 请输入目标版本号 (直接回车使用 $latest_ver): " INPUT_VER
local target_ver="${INPUT_VER:-$latest_ver}"
else
read -p "👉 请手动输入目标版本号 (例如 1.21.50.07): " target_ver
fi
local was_active=false
if systemctl is-active --quiet "$s_name"; then
was_active=true
echo "👉 正在向 screen 发送 'stop' 优雅停服保存地图..."
screen -S "$scr_name" -p 0 -X stuff "$(printf 'stop\r')"
local timeout=30
while systemctl is-active --quiet "$s_name" && [ $timeout -gt 0 ]; do
echo -n "."
sleep 1
((timeout--))
done
echo
if systemctl is-active --quiet "$s_name"; then
echo "⚠️ 超时,强制停止 systemd 服务..."
sudo systemctl stop "$s_name"
fi
fi
# 备份
mkdir -p "$DEFAULT_BACKUP_DIR"
if [ -d "$s_dir/worlds" ]; then
local bkp_file="$DEFAULT_BACKUP_DIR/mc_backup_$(date +%Y%m%d_%H%M%S).tar.gz"
echo "📦 正在备份存档与配置到 $bkp_file ..."
tar -czf "$bkp_file" -C "$s_dir" \
worlds server.properties allowlist.json permissions.json valid_known_packs.json 2>/dev/null || true
fi
# 下载与增量替换
local tmp_zip="/tmp/mc_update_${target_ver}.zip"
local tmp_dir="/tmp/mc_update_extract_${target_ver}"
if ! download_server_zip "$target_ver" "$tmp_zip"; then
echo -e "${C_RED}❌ 下载失败!${C_RESET}"
[ "$was_active" = true ] && sudo systemctl start "$s_name"
rm -f "$tmp_zip"
return
fi
mkdir -p "$tmp_dir"
unzip -q -o "$tmp_zip" -d "$tmp_dir"
echo "👉 增量更新文件(保留所有存档、配置与材质包)..."
rsync -av --exclude='server.properties' \
--exclude='allowlist.json' \
--exclude='whitelist.json' \
--exclude='permissions.json' \
--exclude='valid_known_packs.json' \
--exclude='worlds/' \
--exclude='resource_packs/' \
--exclude='behavior_packs/' \
"$tmp_dir/" "$s_dir/"
rm -f "$tmp_zip"
rm -rf "$tmp_dir"
chmod +x "$s_dir/bedrock_server"
sudo chown -R "$RUN_USER:$RUN_USER" "$s_dir"
echo "👉 重新启动服务..."
sudo systemctl start "$s_name"
sleep 3
if systemctl is-active --quiet "$s_name"; then
echo -e "${C_GREEN}✨ 更新成功!当前已更新至版本 $target_ver 并正常运行!${C_RESET}"
else
echo -e "${C_RED}⚠️ 服务重启失败,请查看日志: sudo journalctl -u $s_name -n 30${C_RESET}"
fi
}
# ---------------------------------------------------------
# 主菜单交互界面
# ---------------------------------------------------------
main_menu() {
clear
echo -e "${C_BOLD}======================================================${C_RESET}"
echo -e "${C_BOLD}${C_GREEN} ⛏️ Minecraft 基岩版 (BDS) 智能管理运维箱${C_RESET}"
echo -e "${C_BOLD}======================================================${C_RESET}"
echo -e " ${C_CYAN}[1]${C_RESET} 🖥️ 查看服务器硬件配置与环境"
echo -e " ${C_CYAN}[2]${C_RESET} 🚀 一键全新搭建 (自动按硬件优化配置)"
echo -e " ${C_CYAN}[3]${C_RESET} 🔍 扫描现有服务端并接管 (配置守护/调优)"
echo -e " ${C_CYAN}[4]${C_RESET} 🔄 无损更新现有服务器核心"
echo -e " ${C_CYAN}[5]${C_RESET} 🎮 进入当前正在运行的控制台 (screen)"
echo -e " ${C_CYAN}[0]${C_RESET} 🚪 退出脚本"
echo -e "${C_BOLD}======================================================${C_RESET}"
read -p "👉 请选择操作编号 [0-5]: " OPTION
case "$OPTION" in
1)
detect_hardware
read -p "按回车键返回菜单..."
main_menu
;;
2)
action_install
;;
3)
action_scan_and_takeover
;;
4)
action_update
;;
5)
read -p "请输入 screen 会话名称 [默认: mc]: " SNAME
screen -r "${SNAME:-mc}"
;;
0)
echo "已退出。"
exit 0
;;
*)
echo "无效选项。"
sleep 1
main_menu
;;
esac
}
# 执行入口
main_menu