2254 字
11 分钟
零成本搭建“半永久”Minecraft服务器:一次对云开发平台规则的自动化探索

前言#

  对于许多技术爱好者和玩家而言,拥有一个私人Minecraft服务器是件极具吸引力的事。它不仅是与朋友共建数字世界的乐园,也是一个绝佳的技术实践平台。在寻求低成本解决方案时,各大云服务商提供的“云原生开发环境”成为了一个理想的备选项。这些平台通常提供配置尚可的容器化Linux环境,对于运行一个中小型MC服务器来说绰绰有余。

  我的探索也由此开始。起初,一切都非常顺利:注册账户,选择环境,上传服务端文件,执行启动命令。几分钟内,一个崭新的Minecraft世界便在云端诞生。然而,喜悦并没有持续太久。次日我便发现,辛苦搭建的服务器已然消失无踪。

  md这服务器比我养的电子宠物死得还快。

  经过一番仔细研究,我终于在平台的文档中找到了原因——一套严格的资源回收机制:

  • 闲置回收:环境创建后,若10分钟内没有活跃的VSCode会话连接,系统将自动回收。
  • 会话超时:用户断开连接后,闲置超过10分钟,环境同样会被回收。
  • 生命周期上限:单个环境的最长连续运行时间不能超过16小时。
  • 周期性强制回收:为优化资源调度,运行超过8小时的环境会在凌晨4点至6点被强制回收。

  这些规则使得常规的部署方式变得毫无意义。一个频繁下线、数据无法保存的服务器,几乎不具备任何实用价值。挑战也因此变得明确:能否在不违反平台核心规则的前提下,通过技术手段,实现服务器的稳定、持续运行?

破局思路:自动化对抗“熵增”#

  直接对抗平台的回收机制是行不通的,但规则本身也揭示了其运行逻辑。系统的“回收”行为是基于“闲置”状态的判断。如果我们能通过程序模拟持续的“活跃”状态,并设计一套机制应对必然到来的周期性重启,问题便迎刃而解。

  由此,我构思了一个自动化运维方案,其核心由两部分构成: 由于cnb具有openapi调用方式

  CNB的api文档

  api图片

  1. 外部编排器 (External Orchestrator)

    • 角色:一个独立的、始终在线的低配服务器(例如廉价VPS或树莓派)。
    • 任务:作为总调度中心,负责在每天固定时间(如上午9点),通过调用平台的API,自动创建或唤醒MC服务器环境。
  2. 内部保活与数据同步脚本 (Internal Keep-Alive & Sync Scripts)

    • 角色:运行在CNB环境内部的一系列自动化脚本。
    • 任务
      • 心跳维持:模拟用户活动,防止环境因“闲置”而被回收。
      • 数据持久化:在环境被销毁前,将世界存档等关键数据备份至外部持久化存储;在环境重启后,再自动恢复这些数据。

  整个工作流形成了一个完美的闭环:每日由外部编排器“重生”服务器,再由内部脚本维持其“生命体征”并确保“记忆”得以延续,周而复始。

自动化核心:构建外部“编排器”#

  实现外部编排器的关键在于与CNB平台的API进行交互。通过阅读API文档,我锁定了三个核心接口:

  1. 启动接口 (POST /.../workspace/start): 作用是触发一个开发环境的启动流程。这是每日“唤醒”操作的起点。
  2. 列表接口 (GET /workspace/list): 用于查询用户下所有环境的状态。通过它,我们可以筛选出正在运行的环境,并获取其唯一标识符sn
  3. 详情接口 (GET /.../workspace/detail/{sn}): 利用sn,获取环境的详细连接信息,其中包含了我们需要的公网地址(IP或域名)。

  基于这三个接口,我编写了以下的Bash脚本,配合cron定时任务,即可实现服务器的每日自动启动。

start_cnb_mc_server.sh (编排器脚本)

#!/bin/bash
# CNB Minecraft Server Orchestrator Script
# 负责每日定时启动服务器,并广播其最新地址
# --- 配置区 ---
API_BASE_URL="https://example.com" # 平台API地址
PRIVATE_TOKEN="YOUR_PRIVATE_TOKEN" # 个人访问令牌,请妥善保管
REPO_PATH="your-group%2Fminecraft-server-repo" # 项目仓库路径 (URL编码)
GIT_BRANCH="main"
DISCORD_WEBHOOK_URL="YOUR_DISCORD_WEBHOOK_URL" # 用于发送开服通知
# --- 日志函数 ---
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] - $1"
}
# 1. 调用API,请求启动环境
log "Step 1: Requesting to start the CNB workspace..."
curl -s -X POST "${API_BASE_URL}/${REPO_PATH}/-/workspace/start" \
--header "Authorization: Bearer ${PRIVATE_TOKEN}" \
--header "Content-Type: application/json" \
--data "{\"branch\": \"${GIT_BRANCH}\"}"
# 2. 等待环境初始化
log "Step 2: Waiting 60 seconds for workspace initialization..."
sleep 60
# 3. 获取正在运行环境的SN标识符
log "Step 3: Fetching the SN of the running workspace..."
SN=$(curl -s "${API_BASE_URL}/workspace/list?status=running" \
--header "Authorization: Bearer ${PRIVATE_TOKEN}" | \
jq -r '.list[0].sn') # 简化处理,取列表的第一个
if [[ -z "$SN" ]]; then
log "Error: Could not find a running workspace SN. Aborting."
exit 1
fi
log "Success: Found running workspace SN: ${SN}"
# 4. 根据SN获取详细连接信息
log "Step 4: Fetching workspace details..."
DETAIL_RESPONSE=$(curl -s "${API_BASE_URL}/${REPO_PATH}/-/workspace/detail/${SN}" \
--header "Authorization: Bearer ${PRIVATE_TOKEN}")
VSCODE_URL=$(echo "$DETAIL_RESPONSE" | jq -r '.vscode')
# 5. 解析出服务器公网地址
log "Step 5: Parsing the server host address..."
SERVER_HOST=$(echo "$VSCODE_URL" | grep -oP 'ssh-remote\+\w+@\K[^?]+')
SERVER_ADDRESS="${SERVER_HOST}:25565"
log "Success: Server address for today is: ${SERVER_ADDRESS}"
# 6. 通过Webhook发送通知
log "Step 6: Sending notification..."
JSON_PAYLOAD="{\"content\": \"Minecraft服务器已启动!今日地址为:\`${SERVER_ADDRESS}\`\"}"
curl -X POST -H "Content-Type: application/json" -d "$JSON_PAYLOAD" "$DISCORD_WEBHOOK_URL"
log "Orchestration complete."

  将此脚本配置到crontab中,即可实现每日无人值守的自动唤醒。

内部心跳:维持环境的“生命体征”#

  为防止服务器在日间因无VSCode连接而“休眠”,我们需要一个内部的心跳脚本。其原理是周期性地创造系统活动,以重置平台的闲置计时器。一个简单有效的方案是利用SSH客户端连接localhost,模拟一次新的终端会话。

keep_alive.sh (心跳维持脚本)

#!/bin/bash
# 该脚本在后台运行,通过周期性创建SSH会话来维持环境活跃
INTERVAL=180 # 180秒(3分钟)
while true; do
echo "[Keep-Alive] - $(date): Sending heartbeat to prevent idle shutdown."
# 通过SSH连接localhost制造系统活动
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 localhost 'echo "Heartbeat session successful"'
sleep $INTERVAL
done

  这个脚本将在环境启动后,由主启动脚本在后台运行,为服务器的持续在线提供保障。

关键挑战:解决数据的“无状态”问题#

  CNB环境的“无状态”(Stateless)特性是本项目最大的挑战。每次重启都意味着环境被重置,若不处理,所有游戏进度都将丢失。

  最初我考虑使用Git来同步世界存档,但很快发现此路不通。MC的地图文件体积庞大且更新频繁,使用Git进行版本控制会迅速导致仓库臃肿,同步效率低下。

  最终,我选择了更为健壮的方案:Rclone + 外部对象存储(S3兼容)。Rclone是一款强大的云存储管理工具,能轻松实现本地文件与云端存储的同步。

  1. 数据恢复:在服务器每日启动时,首先执行rclone sync命令,将云端存储的最新存档完整地同步到本地。
  2. 数据备份:在服务器内部设置一个定时任务,周期性地(例如每30分钟)执行rclone sync,将本地的游戏存档增量同步到云端。

  这套方案不仅解决了数据持久化的问题,而且将数据丢失的风险控制在了两次备份的间隔之内,实现了成本和可靠性之间的良好平衡。

整合与部署:定义最终启动流程#

  最后,需要一个主启动脚本来协调内部的所有任务。这个脚本将作为CNB环境的启动入口(Entrypoint)。

  将CNB项目的启动命令配置为执行此脚本,整个自动化部署便宣告完成。

总结与注意事项#

  通过结合外部API调度和内部自动化脚本,我们成功地将一个具有严格生命周期限制的免费开发环境,改造为了一个能近似7x24小时服务的“半永久”Minecraft服务器。这个项目不仅实现了零成本的游戏服务器部署,更是一次关于自动化运维、IaC(基础设施即代码)和逆向思考的有趣实践。看看我的使用量(   alt text   官方看不到…官方看不到…(其实话又说回来,这个大部分情况下cpu负载不会很高的)

零成本搭建“半永久”Minecraft服务器:一次对云开发平台规则的自动化探索
https://fuwari.vercel.app/posts/2025083001/
作者
木木em哈哈
发布于
2025-08-30
许可协议
CC BY-NC-SA 4.0