想和朋友长期经营一个僵尸末日世界,又不希望房主每次上线才能继续游戏,Project Zomboid(僵尸毁灭工程)专用服务器是更稳定的方案。世界、角色账号、沙盒参数、白名单、模组和备份都保存在 VPS 上,队友可以按自己的时间进入。
本文以 Ubuntu 24.04 LTS、SteamCMD、当前 Build 42 稳定分支和 systemd 为例,从零完成服务端安装、16261/16262 UDP、防火墙、服务器配置、管理员、白名单、世界备份、恢复和自动更新。正文不使用来历不明的游戏镜像,也不会把旧 Build 41 或早期 Build 42 Unstable 教程直接套到当前稳定版。
截至 2026 年 8 月,Project Zomboid 官方已经把 Build 42.20 推送到 Steam 稳定分支,并发布 42.20.1 热修复。因此,新服务器使用 Steam 默认稳定分支即可,不需要再添加旧教程中的 -beta unstable、b42multiplayer 或 Build 41 参数。
这点非常重要:
- 游戏客户端和专用服务器必须位于兼容版本。
- Steam 属性中的
NONE表示当前稳定分支。 - 从 Build 41 升到 Build 42 前必须备份,不能假设旧世界、模组和配置会无损迁移。
- 官方安全更新和多人修复会改变服务端文件,长期关闭更新并不安全。
本文所有命令都以当前稳定分支为目标。以后官方发布新稳定版时,应先阅读补丁说明、备份世界,再在维护窗口更新。
Project Zomboid 没有发布一套能保证任意地图、模组和人数的 VPS 最低配置。玩家分散探索、开车快速加载新区块、大量僵尸、地图模组和 Workshop 内容都会提高 CPU、内存、磁盘与网络压力。下面是便于购买和压测的实战起点,不是官方性能承诺:
| 使用规模 | 建议 VPS 起点 | 磁盘 | 适用场景 |
|---|---|---|---|
| 2–4 人原版服 | 4 个高性能 vCPU、6–8GB 内存 | 50GB NVMe | 私人白名单、生存档 |
| 5–10 人长期服 | 4–6 个高性能 vCPU、10–12GB 内存 | 80GB NVMe | 多人探索、车辆、长期地图 |
| 10 人以上或模组服 | 6–8 核、16GB+ 内存 | 120GB+ NVMe | 地图模组、较高僵尸量、公开服 |
优先选择单核性能稳定、NVMe 延迟低、UDP 质量好的节点。不要只看 vCPU 数量;超售严重的 8 核可能不如稳定的 4 核。机房应靠近主要玩家,并确认服务商允许游戏服务器、提供足够流量以及明确的 DDoS 处理策略。购买前可参考游戏服务器 VPS 配置与线路选择。
| 方式 | 优点 | 代价 | 适合谁 |
|---|---|---|---|
| SteamCMD + systemd | 路径透明、资源开销低、日志直接 | 主要通过 SSH 管理 | 单台 VPS、一个世界 |
| 游戏内 Host | 配置简单、适合临时联机 | 房主必须在线,不是真正的 24 小时服务 | 小队临时开局 |
| Pterodactyl | Web 面板、用户、配额和多实例 | 额外维护 Panel、Wings、数据库 | 多世界或多人运维 |
本文使用 SteamCMD + systemd。若你准备在同一台机器托管 Minecraft、Valheim、CS2 和 Project Zomboid,可考虑Pterodactyl 游戏服务器面板部署指南。
当前常规 Steam 专用服务器应先按最小端口集部署:
| 端口 | 协议 | 用途 | 是否公开 |
|---|---|---|---|
| 16261 | UDP | 主连接与 Steam Relay | 是 |
| 16262 | UDP | 直接连接 | 是 |
| 22 | TCP | SSH 管理 | 仅管理员 IP,或使用实际 SSH 端口 |
| 27015 | TCP | RCON,只有启用后才需要 | 默认不开放 |
Project Zomboid 官方支持人员在端口排障中明确表示,当前游戏只需要开放 16261 和 16262 UDP;网上要求为每位玩家开放一串 TCP 端口的内容多来自旧版本。本文不开 RCON,因此不开放 27015。
服务器配置名使用 survival。它会决定配置文件和世界目录名称,例如:
survival.ini
survival_SandboxVars.lua
Zomboid/Saves/Multiplayer/survival
配置名只使用小写字母、数字和短横线,避免空格和特殊字符引起脚本、备份或服务名混乱。
先更新系统并安装 SteamCMD 所需的基础组件:
sudo apt update
sudo apt upgrade -y
sudo apt install -y curl ca-certificates tar lib32gcc-s1 ufw
创建不能使用密码直接登录的服务账号和固定目录:
sudo adduser --disabled-password --gecos "" pz
sudo install -d -o pz -g pz /opt/steamcmd
sudo install -d -o pz -g pz /opt/pzserver
sudo install -d -m 750 -o root -g pz /var/backups/project-zomboid
不要以 root 身份运行 Java 游戏服务。独立用户能限制进程权限,也能避免 SteamCMD 更新后出现 root 所有的文件,导致下次更新失败。
切换到 pz 用户并下载 Valve 官方 Linux SteamCMD:
sudo -iu pz
cd /opt/steamcmd
curl -fsSL https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz -o steamcmd_linux.tar.gz
tar -xzf steamcmd_linux.tar.gz
./steamcmd.sh +quit
确认入口文件存在:
test -x /opt/steamcmd/steamcmd.sh
Project Zomboid Dedicated Server 的 Steam App ID 是 380870。匿名登录即可下载服务端:
/opt/steamcmd/steamcmd.sh \
+force_install_dir /opt/pzserver \
+login anonymous \
+app_update 380870 validate \
+quit
命令没有 -beta 参数,因此取得当前稳定分支。首次安装或修复损坏文件时使用 validate;日常更新通常不必每次重新校验全部文件。
检查启动脚本和安装大小:
test -x /opt/pzserver/start-server.sh
grep -nE -- '-Xm[sx]' /opt/pzserver/start-server.sh
du -sh /opt/pzserver
如果你看到其他教程仍要求下载 Build 41、为 Build 42 添加 Unstable beta 参数,应先核对发布时间。Build 42.20 已进入默认稳定分支,照搬旧分支参数会造成客户端与服务器版本不一致。
启动脚本中的默认 Java 堆不一定适合你的 VPS。下面以 8GB 内存机器为例,将初始堆设为 2GB、最大堆设为 6GB:
cp /opt/pzserver/start-server.sh /opt/pzserver/start-server.sh.stock
sed -Ei 's/-Xms[0-9]+[gGmM]/-Xms2g/; s/-Xmx[0-9]+[gGmM]/-Xmx6g/' \
/opt/pzserver/start-server.sh
grep -nE -- '-Xm[sx]' /opt/pzserver/start-server.sh
最终输出必须包含 -Xms2g 和 -Xmx6g。不要把 -Xmx 设成 VPS 的全部内存,Ubuntu、文件缓存、SteamCMD 和备份压缩仍需要空间。10–12GB VPS 可以从 -Xms2g -Xmx8g 起步,16GB VPS 可从 -Xms4g -Xmx12g 起步,再根据实际峰值调整。
SteamCMD 更新可能覆盖 start-server.sh,所以每次更新后都要重新检查堆参数。后面的更新脚本会自动重设并验证。
第一次运行必须在交互终端完成,因为服务端会要求创建 admin 账号密码:
cd /opt/pzserver
./start-server.sh -servername survival
按提示输入一个仅用于 Project Zomboid 管理员的强密码。不要与 SSH、Steam 或其他网站复用。等待日志出现:
*** SERVER STARTED ****
然后在服务器控制台输入:
quit
等待进程保存世界并正常退出。不要直接关闭 SSH 或发送强制终止信号。首次运行会在 /home/pz/Zomboid 下生成配置、数据库、日志和世界目录。
退出服务账号:
exit
打开主配置:
sudo -u pz nano /home/pz/Zomboid/Server/survival.ini
在现有文件中找到并调整以下项目,不要用一份旧版本完整配置覆盖 Build 42 自动生成的文件:
Public=true
PublicName=My Project Zomboid Server
PublicDescription=Private Build 42 survival server
Password=REPLACE_WITH_PLAYER_PASSWORD
DefaultPort=16261
UDPPort=16262
MaxPlayers=8
PauseEmpty=true
Open=true
AutoCreateUserInWhiteList=false
DoLuaChecksum=true
SteamVAC=true
RCONPassword=
这些设置实现:公开服务器列表、8 人上限、无人时暂停、首次登录创建账号、Lua 校验与 Steam VAC。RCONPassword 保持为空,本文不启用远程控制端口。
如果要严格白名单,将 Open=false,再由管理员创建玩家账号或加入白名单。不要只设置服务器公共密码就认为有白名单;两者控制的是不同层级。
生成独立玩家密码:
openssl rand -base64 24
将结果写入 Password。配置文件归 pz 用户所有:
sudo chown pz:pz /home/pz/Zomboid/Server/survival.ini
sudo chmod 600 /home/pz/Zomboid/Server/survival.ini
Build 42 的世界规则位于:
/home/pz/Zomboid/Server/survival_SandboxVars.lua
先备份自动生成的文件:
sudo -u pz cp /home/pz/Zomboid/Server/survival_SandboxVars.lua \
/home/pz/Zomboid/Server/survival_SandboxVars.lua.initial
sudo -u pz nano /home/pz/Zomboid/Server/survival_SandboxVars.lua
沙盒字段会随版本更新,不建议从旧 Build 41 教程复制整份 Lua。最稳妥的方法是在同版本客户端的 Host 设置界面创建一个模板,再比较生成的 *_SandboxVars.lua,只迁移你理解的字段。
修改僵尸数量、战利品、车辆、感染或重生规则前先备份世界。某些规则只对新区域或新世界完整生效,不能把“文件保存成功”当成存档已经无损迁移。
创建 unit:
sudo nano /etc/systemd/system/project-zomboid.service
写入:
[Unit]
Description=Project Zomboid Dedicated Server
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=pz
Group=pz
WorkingDirectory=/opt/pzserver
ExecStart=/opt/pzserver/start-server.sh -servername survival
Restart=on-failure
RestartSec=15
KillSignal=SIGTERM
TimeoutStopSec=180
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
加载、启动并查看状态:
sudo systemctl daemon-reload
sudo systemctl enable --now project-zomboid
sudo systemctl status project-zomboid --no-pager
sudo journalctl -u project-zomboid -n 200 --no-pager
日志应出现 *** SERVER STARTED **** 和 Steam 已启用的信息。第一次前台初始化已经创建管理员,因此 systemd 不会卡在密码输入提示。
停止服务后要等待 Java 进程保存退出:
sudo systemctl stop project-zomboid
sudo systemctl status project-zomboid --no-pager
若超过 180 秒仍未退出,先检查日志和磁盘空间,不要立即使用 kill -9。强制终止可能损坏正在写入的区块或玩家数据。
保持当前 SSH 会话不要关闭,先放行 SSH,再开放两个游戏端口:
sudo ufw allow OpenSSH
sudo ufw allow 16261/udp
sudo ufw allow 16262/udp
sudo ufw status numbered
sudo ufw enable
云厂商安全组也必须添加相同 UDP 规则。检查服务监听:
sudo ss -lunp | grep -E ':16261|:16262'
不要为了省事开放 16261–16300 全协议,也不要照搬旧版“每个玩家一个 TCP 端口”的规则。当前官方支持答复将 16261 定义为主连接/Steam Relay,16262 定义为直接连接。
如果使用 pz.example.com,创建指向 VPS IPv4 的 A 记录。普通 Cloudflare 橙云 HTTP 代理不能转发游戏 UDP,应设为 DNS only,或让玩家直接连接公网 IP。
在 Project Zomboid 主菜单选择 Join,添加收藏:
IP: 203.0.113.20
Port: 16261
Server Password: 你在 survival.ini 设置的 Password
Account Username: 玩家自己的服务器用户名
Account Password: 玩家自己的服务器账号密码
公网测试时把示例 IP 换成 VPS 真实地址。服务器密码和玩家账号密码不是同一个字段;玩家应使用独立用户名和密码,不要共享管理员账号。
连接失败时同时查看:
sudo systemctl is-active project-zomboid
sudo journalctl -u project-zomboid -n 250 --no-pager
sudo ss -lunp | grep -E ':16261|:16262'
sudo ufw status numbered
初次启动创建的 admin 账号只用于管理,不用于日常游玩。使用客户端以 admin 登录后,可以在游戏内管理员面板管理玩家和服务器。
需要给另一位玩家管理员权限时,执行游戏管理员命令:
/setaccesslevel "username" admin
撤销权限:
/setaccesslevel "username" none
启用严格白名单时,保持 Open=false,并通过管理员界面创建或允许具体账号。定期检查:
sudo ls -lh /home/pz/Zomboid/db
sudo ls -lh /home/pz/Zomboid/Server
玩家账号和权限数据库同样属于备份范围。不要只备份地图目录,否则恢复后可能丢失白名单、管理员或玩家登录信息。
本文使用 survival 配置名,关键数据通常位于:
/home/pz/Zomboid/Server/
/home/pz/Zomboid/Saves/Multiplayer/survival/
/home/pz/Zomboid/db/
/home/pz/Zomboid/Logs/
用实际文件确认,不要只依赖教程路径:
sudo -u pz find /home/pz/Zomboid -maxdepth 3 -type f | sort | head -n 120
sudo du -sh /home/pz/Zomboid
/opt/pzserver 是可由 SteamCMD 重新下载的程序文件,/home/pz/Zomboid 才是必须保护的世界、配置、账号数据库和日志数据。
在维护窗口停服并打包整个数据目录:
sudo systemctl stop project-zomboid
sudo tar -C /home/pz -czf \
"/var/backups/project-zomboid/pz-data-$(date -u +%Y%m%dT%H%M%SZ).tar.gz" \
Zomboid
sudo systemctl start project-zomboid
sudo systemctl is-active project-zomboid
检查归档:
sudo ls -lh /var/backups/project-zomboid
sudo tar -tzf /var/backups/project-zomboid/pz-data-YYYYMMDDTHHMMSSZ.tar.gz | head -n 100
将示例文件名替换为实际归档。至少同步一份到另一台机器或对象存储,并设置保留周期。完整异地方案可参考VPS 备份与恢复演练指南。
恢复前停止服务并保留当前目录:
sudo systemctl stop project-zomboid
sudo tar -tzf /var/backups/project-zomboid/pz-data-YYYYMMDDTHHMMSSZ.tar.gz | head -n 100
sudo mv /home/pz/Zomboid \
"/home/pz/Zomboid.before-restore-$(date -u +%Y%m%dT%H%M%SZ)"
sudo tar -C /home/pz -xzf \
/var/backups/project-zomboid/pz-data-YYYYMMDDTHHMMSSZ.tar.gz
sudo chown -R pz:pz /home/pz/Zomboid
sudo systemctl start project-zomboid
验证服务、地图和账号:
sudo systemctl status project-zomboid --no-pager
sudo journalctl -u project-zomboid -n 250 --no-pager
sudo du -sh /home/pz/Zomboid/Saves/Multiplayer/survival
使用测试玩家登录,确认出生点、角色、车辆、容器、白名单和管理员权限都正常。验收前保留 Zomboid.before-restore-*,不要立即删除唯一回退副本。
先备份世界、停止服务,再更新 App ID 380870。创建脚本:
sudo nano /usr/local/sbin/update-project-zomboid-server
写入:
#!/usr/bin/env bash
set -euo pipefail
backup_dir=/var/backups/project-zomboid
stamp=$(date -u +%Y%m%dT%H%M%SZ)
was_active=0
install -d -m 750 -o root -g pz "$backup_dir"
if systemctl is-active --quiet project-zomboid; then
was_active=1
systemctl stop project-zomboid
fi
restart_service() {
if [ "$was_active" -eq 1 ]; then
systemctl start project-zomboid
fi
}
trap restart_service EXIT
tar -C /home/pz -czf \
"$backup_dir/pz-before-update-$stamp.tar.gz" \
Zomboid
sudo -u pz /opt/steamcmd/steamcmd.sh \
+force_install_dir /opt/pzserver \
+login anonymous \
+app_update 380870 \
+quit
sed -Ei 's/-Xms[0-9]+[gGmM]/-Xms2g/; s/-Xmx[0-9]+[gGmM]/-Xmx6g/' \
/opt/pzserver/start-server.sh
grep -q -- '-Xms2g' /opt/pzserver/start-server.sh
grep -q -- '-Xmx6g' /opt/pzserver/start-server.sh
chown pz:pz /opt/pzserver/start-server.sh
设置权限并手动测试:
sudo chown root:root /usr/local/sbin/update-project-zomboid-server
sudo chmod 750 /usr/local/sbin/update-project-zomboid-server
sudo /usr/local/sbin/update-project-zomboid-server
sudo systemctl is-active project-zomboid
sudo journalctl -u project-zomboid -n 200 --no-pager
脚本不使用 validate,减少日常更新耗时;发现文件损坏时再手动校验。若 SteamCMD 或堆参数验证失败,脚本会以非零状态退出,并尝试恢复更新前的运行状态。
Project Zomboid 更新可能改变世界或模组兼容性。私人原版服可以在固定低峰窗口自动更新;公开服和模组服更适合通知玩家后手动执行。
创建 service:
sudo nano /etc/systemd/system/project-zomboid-update.service
[Unit]
Description=Update Project Zomboid Dedicated Server
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/update-project-zomboid-server
创建 timer:
sudo nano /etc/systemd/system/project-zomboid-update.timer
[Unit]
Description=Project Zomboid daily maintenance window
[Timer]
OnCalendar=*-*-* 05:50:00
RandomizedDelaySec=10m
Persistent=true
[Install]
WantedBy=timers.target
加载并查看计划:
sudo systemctl daemon-reload
sudo systemctl enable --now project-zomboid-update.timer
systemctl list-timers project-zomboid-update.timer
不要在玩家在线、车辆高速行驶或世界正在保存时强制更新。大型稳定版切换应关闭 timer,先在备份副本上测试。
不要直接在唯一的 Build 41 存档上试运行。安全流程是:
- 停止旧服务器并备份整个
Zomboid目录。 - 保存旧服务端版本、配置和模组清单。
- 在独立目录复制存档,使用当前稳定版测试转换。
- 暂时禁用所有模组,确认原版世界可以加载。
- 检查角色、车辆、容器、地图区块和管理员账号。
- 只有完整验收后,才让正式服务器切换。
官方在 Build 42 开发期间多次提醒版本更新可能破坏旧保存,并建议新存档、无模组复现和更新前备份。即使 Build 42 已进入稳定版,也不代表所有 Build 41 模组或旧存档一定兼容。
想保留长期世界时,备份恢复能力比“能否一次转换成功”更重要。可对照Valheim 专用服务器世界备份流程,建立相同的停服、归档、异机复制和恢复验收习惯。
先让原版服务器稳定运行,再添加模组。官方在 2026 年发布过与恶意 Workshop 内容有关的安全公告,并持续修补 Build 41/42 安全问题;因此不能把 Workshop 订阅量当成安全审计。
添加模组前:
- 核对模组是否明确支持当前 Build 42 稳定版。
- 记录
WorkshopItems和Mods的顺序及版本。 - 检查作者、更新记录、评论和外部下载要求。
- 不执行模组要求的来源不明脚本或二进制。
- 在备份副本上测试,不直接污染正式世界。
- 更新后先以无模组世界复现崩溃,再判断是游戏还是模组问题。
不要让无人值守 timer 自动跨越大型版本更新。模组服的更新窗口应包含备份、模组兼容检查和回滚时间。
记录玩家高峰、驾驶穿越新区块和世界保存时的数据:
free -h
df -h /opt/pzserver /home/pz/Zomboid /var/backups/project-zomboid
uptime
ps -eo pid,%cpu,%mem,rss,etime,cmd | grep '[z]ombie.network.GameServer'
sudo journalctl -u project-zomboid --since "30 minutes ago" --no-pager
重点关注:
- 开车进入新区块时单核满载:换单核更强、磁盘延迟更低的节点。
- 玩家分散后内存快速上涨:降低人数、地图范围或模组数量,再评估扩容。
- 保存时卡顿或回档:检查 NVMe 延迟、剩余空间和强制终止记录。
- 晚高峰延迟明显:检查 UDP 丢包、机房线路和邻居超售。
- 日志或备份写满根分区:设置保留周期,并把异地副本移出本机。
不要通过无限提高 -Xmx 掩盖模组内存泄漏。官方 42.20.1 热修复包含多人区块卸载与内存使用修复,保持当前安全稳定版本身就是性能维护的一部分。
说明你跳过了第一次前台初始化。停止 systemd,使用 pz 用户前台运行:
sudo systemctl stop project-zomboid
sudo -iu pz
cd /opt/pzserver
./start-server.sh -servername survival
设置 admin 密码、等待 SERVER STARTED,输入 quit,退出账号后再启动 systemd。
检查服务端安装清单并更新稳定分支:
grep -n 'buildid' /opt/pzserver/steamapps/appmanifest_380870.acf
sudo /usr/local/sbin/update-project-zomboid-server
sudo journalctl -u project-zomboid -n 200 --no-pager
确认客户端 Betas 选择 NONE。不要让客户端使用 Build 41、旧 Unstable,而服务器使用当前稳定版;也不要通过删除世界解决版本不一致。
依次检查配置、监听和安全组:
sudo grep -E '^(Public|PublicName|DefaultPort|UDPPort)=' \
/home/pz/Zomboid/Server/survival.ini
sudo ss -lunp | grep -E ':16261|:16262'
sudo ufw status numbered
sudo journalctl -u project-zomboid -n 250 --no-pager
使用公网 IP 和 16261 直接加入,排除列表刷新问题。确认 UFW 与云安全组都开放 UDP 16261/16262,域名没有启用普通 HTTP 代理。
这通常是 16261/16262 UDP、云安全组、版本或 Steam 状态问题。先用无模组客户端测试,再查看日志中的 Steam、RakNet 和连接错误:
sudo journalctl -u project-zomboid -n 300 --no-pager | \
grep -iE 'steam|raknet|connect|error|failed'
不要无依据开放 50000–65000 全端口。官方支持答复指出游戏本身只需要 16261 和 16262;额外高位端口需求更可能来自主机商、NAT 或防火墙配置异常。
SteamCMD 可能覆盖启动脚本。检查堆参数:
grep -nE -- '-Xm[sx]' /opt/pzserver/start-server.sh
free -h
sudo journalctl -u project-zomboid -n 250 --no-pager | grep -iE 'memory|heap|oom|killed'
重新设置适合 VPS 的 -Xms/-Xmx,并确认更新脚本的两个 grep -q 验证通过。不要把最大堆设置为全部物理内存。
先恢复模组前备份,在配置中暂时清空 WorkshopItems 与 Mods,用原版服务器复现:
sudo systemctl stop project-zomboid
sudo cp /home/pz/Zomboid/Server/survival.ini \
/home/pz/Zomboid/Server/survival.ini.failed-mods
sudo -u pz nano /home/pz/Zomboid/Server/survival.ini
sudo systemctl start project-zomboid
sudo journalctl -u project-zomboid -n 300 --no-pager
确认原版正常后逐批恢复模组。一次启用几十个模组会让冲突、恶意内容和版本错误无法定位。
- SteamCMD 安装 App ID 380870,未添加旧 Unstable beta 参数。
- 客户端与服务器都使用当前 Build 42 稳定分支。
- 服务以独立
pz用户运行,不使用 root。 - 首次前台启动已创建 admin,systemd 不会等待交互输入。
-
systemctl is-active project-zomboid返回active。 - 日志出现
*** SERVER STARTED ****和 Steam 启用信息。 - 16261/16262 UDP 已在 UFW 与云安全组放行。
- 没有开放未使用的 RCON 或大段高位端口。
-
survival.ini和沙盒 Lua 来自当前版本自动生成文件。 - Java 堆参数适合 VPS,更新后会重新验证。
- admin 账号不用于日常游玩,公开服已配置白名单策略。
- 世界、配置、账号数据库和日志一起备份。
- 已完成一次恢复并验证角色、车辆、容器和权限。
- 原版服务器验收后才添加 Build 42 兼容模组。
- 大型更新前会暂停 timer、通知玩家并保留可回滚副本。
在 VPS 上运行 Project Zomboid Build 42,关键不是复制一条 SteamCMD 命令,而是让客户端和 App ID 380870 保持同一稳定分支,正确开放 16261/16262 UDP,先完成交互式管理员初始化,再交给 systemd 常驻。
真正需要保护的是 /home/pz/Zomboid 下的世界、配置、玩家数据库和权限。每次更新前停服备份、重新校验 Java 堆参数,并先用无模组世界复现问题,能显著降低版本迁移、Workshop 内容和强制终止造成的回档风险。
