开服这事儿,说穿了就是把一个 jar 包喂给 Java,再让外面的人能连上你。但真动手的时候你会发现,光是一个 Java 版本对不上,就能让你对着满屏报错发半小时呆。我前后给朋友和自己搭过七八个服,从原版生存到几十个模组的大包,也在云服务器上折腾过一段时间,踩过的坑大概能凑出一份避雷清单。这篇就把 Minecraft 服务器搭建这件事从零到能跑、再到能长期稳定运行,完整捋一遍。
不管你之前有没有碰过命令行,只要你能照着步骤敲、能看懂一点点报错信息,这篇内容就能帮你把服开起来。全程我会说清楚每一步"为什么这么做",而不是甩给你一串命令让你背。涉及 Minecraft、服务器的关键选择,我都会给判断依据。看完之后你至少能自己判断:我到底该用原版服务端还是 Forge 加载器,我该买多大的云服务器,我该怎么让服在崩了之后自动重启。
1. 先想清楚要搭什么样的服:需求拆解与方案选型
很多人一上来就下载服务端,结果装了原版发现朋友想玩模组,装了模组又发现配置不够,白折腾一轮。开服的第一步其实不是动手,而是想清楚三个问题:玩什么、在哪开、给谁玩。这三个问题的答案直接决定了你后面所有的技术选型。
1.1 服务器类型决定你后面所有操作
从玩法维度看,常见的服分三类:原版生存服、模组服、插件服。原版服只需要官方提供的服务端,最轻、最稳、最容易维护,适合三五个朋友一起打打生存、造造建筑。模组服需要 Forge 或 Fabric 这类加载器,模组数量一上去,内存和 CPU 的消耗是原版的几倍甚至十几倍。插件服则是 Bukkit、Spigot、Paper 这套体系,服务端本身兼容原版,但支持插件扩展功能,比如领地保护、经济系统、传送点,适合想开一个半公开小服的人。
判断标准很直接:如果你只是想和朋友玩原版或者加几个小模组,选原版或 Fabric;如果要跑整合包,尤其是有几百个模组的那种,就得用 Forge 加载器,并且内存至少给到 8GB 以上。想开带管理功能的公开服,Paper 是现在的主流选择,它在 Spigot 基础上做了大量性能优化,同样的机器能多带不少人。
注意:Paper、Spigot 这类服务端和 Forge 模组是两套体系,不能混着装。想同时要模组和插件,只能走 Arclight、Mohist 这类混合端,但兼容性坑不少,新手不建议一上来就碰。
1.2 本地开服还是租云服务器
这个问题的核心是"别人能不能连上你"。本地开服,也就是在自己电脑上跑服务端,优点是零成本、改配置方便,缺点是电脑一关服就没了,而且大多数家庭宽带没有独立公网 IP,外面的人压根连不进来。租云服务器则相反,机器 7×24 小时在线,有独立公网 IP,缺点是每个月要花钱,而且配置越高越贵。
我的建议是分两步走。第一阶段,先在自己电脑上把服跑起来,验证配置、模组、地图都没问题,这一步用本地环境最省事,改一次配置重启只要十几秒。第二阶段,等玩法稳定了,再考虑搬到云服务器上。选购的时候别一上来就买高配,2 核 4G 的入门款跑原版 5 到 10 人完全够用,月付成本通常在几十块钱这个量级;跑模组包则建议 4 核 8G 起步,具体还要看你模组包的体量。
带宽也是容易被忽略的一环。云服务商的"带宽"通常指公网出口带宽,1Mbps 大概能支撑三四个玩家流畅移动,5Mbps 能撑十人左右。很多服务商提供"按流量计费"模式,对开服这种长时间在线但流量不算特别大的场景,按月带宽包更划算。
1.3 版本与环境的对应关系
Minecraft 的 Java 版对运行环境有硬性要求,版本选错就是启动不了的报错。下面这张表是我实际验证过的对应关系,照着选基本不会错:
| Minecraft 版本 | 服务端需要的 Java 版本 | 备注 |
|---|---|---|
| 1.12.2 及更早 | Java 8 | 老整合包的重灾区,必须用 8 |
| 1.13 - 1.16.5 | Java 8 或 Java 11 | 模组生态成熟,整合包最多 |
| 1.17 | Java 16 | 地形生成改动大,性能吃紧 |
| 1.18 - 1.20.4 | Java 17 | 目前最稳的模组版本区间 |
| 1.20.5 及以后 | Java 21 | 新版本服务端普遍要求 21 |
实操心得:一台机器上同时装多个 Java 版本是很常见的做法。Windows 下装在不同目录,启动脚本里用绝对路径指定
javaw.exe;Linux 下用update-alternatives管理,或者直接在启动脚本里写死/usr/lib/jvm/java-17-openjdk/bin/java。这样你就能同时维护一个 1.12.2 的老整合包和一个 1.20 的新服。
2. 开服前的准备工作:Java、内存与目录
环境准备这一步看着无聊,但它决定了你后面是顺风顺水还是天天救火。我见过太多人跳过这一步,结果服务端起来三分钟就 OOM 崩掉,然后开始怀疑人生。
2.1 Java 环境安装与验证
Windows 上最省事的做法是去 Adoptium(Eclipse Temurin)或者微软的 OpenJDK 构建下载安装包,装完之后把JAVA_HOME环境变量配好,再把%JAVA_HOME%\bin加进Path。验证方式很简单,开一个命令提示符敲:
java -version能打印出版本号就说明装好了。Linux 上更简单,Debian 系直接apt install openjdk-17-jre-headless,注意要装headless版本,服务端没有图形界面需求,装带界面的反而多占几十兆内存和一堆依赖。
这里有个新手特别容易踩的坑:java -version显示的是 1.8,但你实际需要 17。原因是系统里装了多个 Java,Path里排在最前面的是老版本。解决办法是where java(Windows)或which -a java(Linux)看看都有哪些,然后把需要的那个提前。
2.2 内存该怎么分配
内存分配是开服里最玄学也最有讲究的一环。核心原则是:给服务端的内存不能超过物理内存的 70%。因为 JVM 除了堆内存,还要占用堆外内存、线程栈、直接内存,你给满 8G 堆,物理内存 8G,系统自己就没得用了,反而更容易崩。
具体给多少,我按经验给个参考区间:
| 场景 | 建议堆内存 | 说明 |
|---|---|---|
| 原版 2-5 人 | 2G | 再多就是浪费 |
| 原版 10 人 + 少量插件 | 4G | Paper 优化后很能扛 |
| 50 个模组左右 | 6G | 注意模组之间有兼容问题 |
| 150 个模组以上整合包 | 8G-12G | 大部分整合包作者会写明推荐值 |
| 大型公开服 | 16G 起 | 通常需要专门的性能调优 |
给内存的方式是在启动命令里加参数,-Xms4G -Xmx4G这两个值建议设成一样。为什么?因为设成一样可以避免 JVM 在运行过程中反复调整堆大小带来的停顿,对游戏这种对卡顿敏感的应用来说,稳定性比"省内存"重要得多。
2.3 目录结构规划
服务端放哪里不重要,重要的是养成目录分离的习惯。我一般会这样组织:
minecraft-server/ ├── server.jar # 服务端本体 ├── start.bat / start.sh # 启动脚本 ├── eula.txt # 用户协议 ├── server.properties # 主配置 ├── world/ # 主世界存档 ├── world_nether/ # 下界 ├── world_the_end/ # 末地 ├── plugins/ 或 mods/ # 插件或模组 ├── logs/ # 日志 └── backups/ # 备份存档把备份目录放在服务端目录里面其实有个小风险——万一你整个目录打包迁移,备份也跟着走,体积会爆掉。更稳妥的做法是把备份放到另一个磁盘或者另一个目录。这一点后面讲自动备份的时候会再细说。
3. 原版服务端搭建全流程实操
环境准备好之后,原版服的开服流程其实很短:下载 jar、同意协议、改配置、启动、放行端口。我把每一步的细节都拆开说。
3.1 获取服务端与同意 EULA
服务端 jar 从官方启动器对应的下载页拿,或者用服务端专用的下载地址。拿到之后放进你的服务端目录,重命名成server.jar,方便后面写脚本。第一次启动的时候,服务端会生成一个eula.txt,内容里有个eula=false,你必须改成eula=true才能继续。
关于这个协议,说一句就够了:它是对服务端使用条款的确认,你自己玩或者小范围朋友玩,勾选是正常流程。不勾选的话服务端会直接退出,这是设计如此,不是 bug。
3.2 server.properties 关键项逐个说明
这个文件是服务器的"总开关",第一次启动后会自动生成,里面几十行配置,真正需要动的大概十来个。我把最关键的整理成表:
| 配置项 | 默认值 | 建议值 | 说明 |
|---|---|---|---|
online-mode | true | 保持 true | 正版验证,关掉等于谁都能冒名进服 |
white-list | false | 小服建议 true | 配合whitelist.json使用 |
max-players | 20 | 按实际 | 设太大反而容易被挤爆 |
view-distance | 10 | 6-8 | 最影响性能的选项之一 |
simulation-distance | 10 | 4-6 | 怪物、红石、作物更新的范围 |
difficulty | easy | 按需 | 生存服常用 normal |
pvp | true | 按需 | 纯建造服可以关 |
spawn-protection | 16 | 0 | 有插件时建议关掉避免冲突 |
motd | 一段默认文本 | 自定义 | 客户端列表里显示的那行字 |
enable-command-block | false | 按需 | 很多地图玩法依赖它 |
allow-flight | false | 模组服开 true | 装了飞行模组必须开 |
view-distance和simulation-distance这两个是最值得调的。把view-distance从 10 降到 6,服务器的 CPU 和内存压力能降三分之一以上,而玩家在大多数场景下几乎感觉不到差别,因为远处的地形本来也是雾里看花。如果你的服经常 TPS 掉到 15 以下,先动这两个参数,比升级配置便宜多了。
3.3 启动脚本怎么写才省事
不管你用什么系统,都建议把启动命令写进脚本,而不是每次手敲。Windows 上建一个start.bat:
@echo off java -Xms4G -Xmx4G -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar server.jar nogui pauseLinux 上建一个start.sh,记得chmod +x start.sh:
#!/bin/bash java -Xms4G -Xmx4G -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar server.jar nogui脚本里加pause(Windows)或者不加重启逻辑,是为了让窗口不闪退,你能看到报错。等调试稳定了,再把脚本改成while true循环,让服务端崩了自动拉起来:
#!/bin/bash while true do java -Xms4G -Xmx4G -XX:+UseG1GC -jar server.jar nogui echo "服务端已退出,5 秒后重启..." sleep 5 done注意:自动重启循环一定要配合日志和备份。有些崩溃是存档损坏导致的,无限重启只会让损坏的地图越来越大,最后连备份都救不回来。
3.4 端口放行与连通性测试
服务端默认监听 25565 端口。本地测试很简单,客户端里加服务器地址填localhost或者127.0.0.1就能进。
要让外面的朋友连进来,分两种情况。云服务器上,你需要在服务商的控制台里找到"安全组"或"防火墙"设置,放行 TCP 25565 入方向。很多人卡在这一步,服务端明明在跑,日志也正常,就是连不上,八成是安全组没开。家里开服则需要在路由器上做端口转发,把外网的 25565 映射到内网这台机器的 25565,同时确认宽带运营商给的是公网 IP。
测试连通性有个小技巧:在自己的电脑上关掉客户端,用命令行的telnet 你的IP 25565试一下,能连上说明端口通了,连不上就是网络层的问题,跟服务端本身没关系。这个判断能帮你省下大量无谓的排查时间。
4. 进阶:用 Forge 加载器开一个模组服
模组服是绝大多数人真正想开的东西,也是坑最多的地方。核心难点不在安装,而在于"客户端和服务端必须一致"这件事。
4.1 Forge 与 Fabric 怎么选
这两个是目前主流的模组加载器。Forge 历史长、整合包多、文档全,缺点是启动慢、重。Fabric 轻量、启动快、更新跟得紧,缺点是大型整合包相对少一些,很多经典的科技、魔法类模组只有 Forge 版本。
选择依据很实际:你要玩的那个整合包用什么加载器,你就用什么。想玩某个人气科技整合包,那基本就是 Forge 了。想自己拼几个轻量模组,比如优化类、小地图、物品栏整理,Fabric 体验会更好。千万别为了"先进"去选,模组生态才是决定因素。
4.2 Forge 服务端的安装流程
Forge 服务端不是下载一个现成的 jar 就能用,它需要先跑安装器生成服务端文件。流程大概是:
- 去 Forge 官网找到对应 Minecraft 版本的安装器,下载
forge-<版本>-installer.jar。 - 新建一个空目录,把安装器放进去。
- 执行
java -jar forge-<版本>-installer.jar --installServer。 - 安装器会下载依赖并生成
libraries目录、run.sh/run.bat和几个配置文件。 - 第一次执行
run.sh,它会生成eula.txt,改成 true 后再次启动。
这个过程第一次跑会比较慢,因为它要下载一堆依赖库。国内网络环境下,下载库文件有时候会卡住,耐心等或者换个时间段再试通常就好。
实操心得:安装 Forge 服务端时用的 Java 版本,必须和正式运行时一致。我遇到过一次,用 Java 8 装的 Forge 1.18 服务端,安装过程没报错,但启动时报了一堆字节码版本不兼容,排查了半小时才发现是装的时候用错了 JDK。
4.3 模组放置与冲突排查
服务端的模组放在mods目录下,把客户端用的模组文件复制过去。但这里有三个必须注意的点:
第一,只有服务端模组必须放服务端。有些模组是纯客户端的功能,比如光影、性能优化、界面美化,这些放到服务端不但没用,还可能导致启动失败。判断方法很简单:模组页面一般会标注Client、Server或Both。
第二,模组版本号要和 Minecraft 版本严格对应。1.20.1 的模组放到 1.20.4 的服上,大概率直接崩。
第三,模组的配置文件是分开的。很多模组在config目录下有自己的配置文件,服务端的配置和客户端的配置是两回事。比如某个模组限制某些方块的使用,你在服务端配了,客户端还得自己配一遍才生效。
排查模组冲突有个通用方法:先只放必须的核心模组,能起来再一半一半地加,崩了就缩小范围。日志里通常会写明是哪个模组导致的,搜索模组名找对应的问题报告,比盲目删模组高效得多。
4.4 客户端一致性的实现方式
模组服最麻烦的就是让每个玩家都能进得来。标准做法是把客户端需要的模组打个包,发给每个朋友,让他们用同版本的 Forge 客户端加载。更省事的做法是用整合包格式,把mods、config、resourcepacks一起打包,别人导入启动器就能用。
需要特别注意版本对齐:客户端 Forge 版本、模组版本、Minecraft 版本三者都要和服务端一致。社区里很多"连接被拒绝""注册表不匹配"的报错,本质都是版本对不上。与其一个个排查,不如一开始就统一用同一份文件。
5. 服务器长期运行:性能调优、备份与安全
服能跑起来只是开始,真正让人头疼的是它跑着跑着开始卡、存档丢了、或者被乱七八糟的人连进来。这一节讲的是"运维"层面的事。
5.1 JVM 启动参数调优
默认的 JVM 参数对 Minecraft 这种"大量短生命周期对象"的应用并不友好,很容易出现 GC 停顿造成的周期卡顿。现在主流的做法是使用 G1 垃圾回收器配合一组社区验证过的参数,这套参数最早由一位叫 Aikar 的开发者整理,所以常被叫做 Aikar's Flags。
一个 4G 堆的参考配置:
java -Xms4G -Xmx4G \ -XX:+UseG1GC \ -XX:+ParallelRefProcEnabled \ -XX:MaxGCPauseMillis=200 \ -XX:+UnlockExperimentalVMOptions \ -XX:+DisableExplicitGC \ -XX:G1NewSizePercent=30 \ -XX:G1MaxNewSizePercent=40 \ -XX:G1HeapRegionSize=8M \ -XX:G1ReservePercent=20 \ -XX:G1HeapWastePercent=5 \ -XX:G1MixedGCCountTarget=4 \ -XX:InitiatingHeapOccupancyPercent=15 \ -XX:G1MixedGCLiveThresholdPercent=90 \ -XX:G1RSetUpdatingPauseTimePercent=5 \ -XX:SurvivorRatio=32 \ -XX:+PerfDisableSharedMem \ -XX:MaxTenuringThreshold=1 \ -jar server.jar nogui这套参数看起来吓人,但核心逻辑就三条:让新生代占更大比例(模组服对象创建太频繁)、控制单次 GC 停顿不超过 200 毫秒、减少不必要的全量回收。实测下来,在同样的硬件上,服里人多的时候卡顿会明显减少。
如果你用的是整合包,注意看整合包作者有没有提供推荐的启动参数,有的话优先用他们的,因为那个数字是针对具体模组集合调出来的。
5.2 自动备份:宁可多备不可少备
存档丢失是开服玩家最痛的事故,没有之一。常见原因有三个:服务端崩溃时正在写存档、磁盘写满、以及误删。手动备份不现实,人总会忘,所以必须自动化。
Linux 下最简单的方案是 crontab 定时执行一个备份脚本:
#!/bin/bash DATE=$(date +%Y%m%d_%H%M%S) BACKUP_DIR=/data/mc-backups WORLD_DIR=/data/minecraft-server # 先给服务端发送保存指令,再打包 screen -S mc -p 0 -X stuff "save-all\n" sleep 10 tar -czf $BACKUP_DIR/world_$DATE.tar.gz -C $WORLD_DIR world world_nether world_the_end # 只保留最近 7 天的备份 find $BACKUP_DIR -name "world_*.tar.gz" -mtime +7 -delete这里有个关键细节:打包前必须先让服务端save-all。直接复制正在被写入的世界文件,可能得到一份损坏的存档,恢复的时候反而更麻烦。如果服务端是用screen或者tmux起的会话,就按上面那样发指令;如果是 systemd 管理的,可以用systemctl或者直接连 RCON。
还有一个更稳的思路是"快照式备份",有条件的话用文件系统快照或者云服务商的磁盘快照功能,秒级完成且不影响运行。但成本会高一些,看你怎么权衡。
5.3 白名单、验证与基础防护
公开服最容易遇到的问题是被人恶意破坏,小服也难免被扫到。基础防护有这几点:
- 开启
white-list,只让名单里的人进。加人用whitelist add 玩家名,记得whitelist reload生效。 online-mode保持 true,这样玩家 ID 是经过验证的,别人没法冒用名字。如果你有朋友用离线启动器,要么给他开个正版,要么接受整个服关掉验证的风险。- 定期更新服务端,尤其是 Paper 这类会跟进安全修复的。老版本的服务端有些已知的漏洞会被扫描工具批量利用。
- 不要用管理员账号跑服务端。Linux 下专门建一个普通用户跑服,万一被攻击,损失范围也能控制住。
注意:装了插件之后,
server.properties里的spawn-protection建议设成 0,因为大部分领地类插件有自己的保护机制,两者叠加会导致玩家在自己领地里也放不了方块,这种"玄学问题"排查起来特别费时间。
5.4 远程管理与日常巡检
云服务器上的服,日常管理基本靠 SSH 或者 Web 面板。SSH 登录之后用screen或tmux把服务端跑在后台会话里,这样你断开连接服也不会停。查看状态用screen -r mc切回会话,或者用tail -f logs/latest.log实时看日志。
日常巡检我一般看三个东西:TPS(用/tps命令,Paper 自带)、内存占用(/memory或者直接top看 Java 进程)、以及磁盘剩余空间。TPS 长期低于 18 就说明该优化了,内存持续接近上限说明该加内存或者排查内存泄漏,磁盘剩余低于 20% 就要清理日志和备份。
装个 Web 面板(比如开源的 MCSManager 或者 Pterodactyl)会方便很多,网页上就能看控制台、改配置、管理文件、分权限。缺点是面板本身也是一层服务,需要额外维护,而且面板的漏洞如果被利用,风险比裸跑服务端更高。小服的话,SSH + screen 其实完全够用。
6. 常见问题排查实录
这一节是我自己遇到和朋友问得最多的十几个问题,整理成速查表,遇到问题先对号入座。
| 现象 | 最可能的原因 | 处理方式 |
|---|---|---|
| 启动后立刻退出,日志只有几行 | 没同意 EULA | 打开eula.txt改成 true |
报UnsupportedClassVersionError | Java 版本过低 | 换成对应版本要求的 Java |
报Could not reserve enough space | 内存参数大于物理内存 | 调小-Xmx |
| 服务端在跑但连不上 | 端口没放行 | 检查云服务商安全组或路由器端口转发 |
| 别人能连,朋友连不上 | 他用的是离线启动器 | 确认online-mode和客户端类型 |
| 玩一会儿就卡顿 | view-distance太大 | 降到 6 试试 |
| 报 "Mismatched mod channel" | 客户端服务端模组不一致 | 核对模组列表和版本 |
| 存档能进但地形错乱 | 存档损坏 | 从备份恢复,检查是否在写入时被复制 |
| 后台看不到输出 | 服务端跑在别的会话里 | 用screen -r切回去 |
| 玩家被踢出,提示超时 | 网络抖动或带宽不足 | 查看带宽占用,考虑升级 |
| 命令方块不生效 | 配置里被关了 | enable-command-block=true |
| 服务器时间不对 | 系统时区未设置 | Linux 用timedatectl设置时区 |
关于"存档损坏"这一条我想多说两句,因为它是唯一一个不可逆的问题。判断方法:进服之后如果地形出现明显的区块断裂、建筑一半悬空、或者某些区块反复重载,基本就是存档受损了。这时候不要继续玩,立刻停服,从最近的备份恢复,越晚处理损坏范围越大。有条件的可以在服务器上开一份"只读快照",每天固定时间点打一份,恢复起来更省心。
还有一类问题比较隐蔽:服务端看起来一切正常,日志没有报错,但玩家会莫名其妙掉线。这种大概率是内存或者 CPU 打满导致的心跳超时。排查方式是开个监控,记录 Java 进程的内存曲线和 CPU 使用率,如果发现内存呈现锯齿状上升然后突然回落,并且回落时伴随一次长时间停顿,那就是 GC 参数的问题,回到 5.1 节调参数。
对于玩票性质的服,我个人觉得不用追求 100% 的稳定性,重点是把备份做扎实,出问题能从备份里捞回来,这就够了。真正需要长期在线的服,就老老实实上监控、上自动重启、上定时快照,把这些机械化的活儿交给脚本,人只负责在出事的时候做决策。