好朋友找我玩minecraft,正好之前租了一台腾讯云学生主机,主机配置一般,不过感觉几个人玩minecraft应该还是能撑得住,果断搞起,回想当年一起联机的快乐,瞬间兴奋了起来
因为有一个好朋友在美利坚,所以我本来以为带宽会是一个大问题,事实证明带宽问题不大,内存问题很大… 本来玩的好好的,突然服务器说挂就挂,一查发现是Out of memory,搞得心态炸裂
本文简单记录一下搭建minecraft服务器和尝试解决内存溢出问题的过程
服务器配置:1核 2G内存 60GSSD 带宽6Mbps
操作系统:CentOS Linux release 7.6.1810
minecraft服务端核心:mojiang官方核心,没有使用任何mod和插件,版本1.17.1,目前最新版
(2023.03.08更新 目前minecraft最新版1.19.3,使用CentOS Linux release 8.2.2004 以下方法依然可用XD)
1. 先决条件
由于minecraft 1.17版本开始不能使用java8,必须使用java16+,这里直接安装java-latest
(1) Java
安装 jdk
yum -y install java-latest-openjdk*
检查jdk版本
java -version
(2) 安装构建mcrcon工具所需的软件包
sudo yum install git
sudo yum group install "Development Tools"
2. 创建系统用户
不建议直接使用root作为运行minecraft的用户
可创建一个没有设置密码,不能用SSH登录的系统用户minecraft,并设置 /opt/minecraft 为用户主目录。
sudo useradd -r -m -U -d /opt/minecraft -s /bin/bash minecraft
3. 安装minecraft服务端
(1) 切换到用户minecraft
sudo su - minecraft
(2) 在主目录创建三个新目录
mkdir -p ~/{backups,tools,server}
backups:存放备份数据
tools:存放工具,包含mcrcon客户端,同时可编写一些自定义脚本用于服务器管理
server:minecraft服务端目录,包含地图和用户数据
(3) 安装mcrcon客户端
从git仓库clone到本地并编译
cd ~/tools && git clone https://github.com/Tiiffi/mcrcon.git
cd ~/tools/mcrcon
gcc -std=gnu11 -pedantic -Wall -Wextra -O2 -s -o mcrcon mcrcon.c
测试是否编译成功
./mcrcon -h
输出像这样就是编译成功
Usage: mcrcon [OPTIONS]… [COMMANDS]…
Sends rcon commands to Minecraft server.Option:
-h Print usage
-H Server address
-P Port (default is 25575)
-p Rcon password
-t Interactive terminal mode
-s Silent mode (do not print received packets)
-c Disable colors
-r Output raw packets (debugging and custom handling)
-v Output version informationServer address, port and password can be set using following environment variables:
MCRCON_HOST
MCRCON_PORT
MCRCON_PASSCommand-line options will override environment variables.
Rcon commands with arguments must be enclosed in quotes.Example:
mcrcon -H my.minecraft.server -p password “say Server is restarting!” save-all stop
(4) 下载minecraft服务端
可在 minecraft官网 获取最新官方服务端下载链接
wget https://launcher.mojang.com/v1/objects/a16d67e5807f57fc4e550299cf20226194497dc2/server.jar -P ~/server
(4) 初次执行并配置服务器
第一次并不会运行minecraft程序,只是执行初始化
cd ~/server
java -Xmx1024M -Xms1024M -jar server.jar nogui
会显示
[main/ERROR]: Failed to load properties from file: server.properties
[main/WARN]: Failed to load eula.txt
[main/INFO]: You need to agree to the EULA in order to run the server. Go to eula.txt for more info.
表示需要同意协议并且设置server.properties配置文件。
打开eula.txt文件,然后将eula=false更改为eula=true即可
vim ~/server/eula.txt
eula=true
接下来按照需要编辑配置文件
vim ~/server/server.properties
Minecraft Wiki 上有详细介绍每个配置选项的含义,可自行按照需要配置。
这里为了使用rcon客户端,需要配置以下几个配置项
rcon.port=25575
rcon.password=此处填写你想要设置的rcon密码
enable-rcon=true
(5) 将minecraft设置为守护进程
在Systemd目录下添加一个minecraft.service
sudo vim /etc/systemd/system/minecraft.service
添加以下配置
[Unit]
Description=Minecraft Server
After=network.target
[Service]
User=minecraft
Nice=1
KillMode=none
SuccessExitStatus=0 1
ProtectHome=true
ProtectSystem=full
PrivateDevices=true
NoNewPrivileges=true
WorkingDirectory=/opt/minecraft/server
ExecStart=/usr/bin/java -XX:ErrorFile=/opt/minecraft/server/err/hs_err_%Y-%m-%d-%H:%M:%S.log -Xmx1024M -Xms1024M -jar server.jar nogui
ExecStop=/opt/minecraft/tools/mcrcon/mcrcon -H 127.0.0.1 -P 25575 -p 此处填写你设置的rcon密码 stop
[Install]
WantedBy=multi-user.target
启动配置中Xmx和Xms分别为给虚拟机分配的可用最大和最小堆空间,这个根据自己的主机配置按需设置即可。
更新配置并开启服务端
sudo systemctl daemon-reload
sudo systemctl start minecraft
查看守护进程状态
sudo systemctl status minecraft
● minecraft.service - Minecraft Server
Loaded: loaded (/etc/systemd/system/minecraft.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2021-08-20 21:03:03 CST; 1h 52min ago
Main PID: 7062 (java)
CGroup: /system.slice/minecraft.service
└─7062 /usr/bin/java -XX:ErrorFile=/opt/minecraft/server/err/hs_err_%Y-65e3e…
设置开机启动
sudo systemctl enable minecraft
记得设置防火墙,放通对应端口号的请求,默认端口号为25565,在server.properties中也可以自己改端口号
4. 设置每日备份
切换到minecraft用户
sudo su - minecraft
编写备份脚本
vim /opt/minecraft/tools/backup.sh
#!/bin/bash
function rcon {
/opt/minecraft/tools/mcrcon/mcrcon -H 127.0.0.1 -P 25575 -p 此处填写你设置的rcon密码 "$1"
}
rcon "save-off"
rcon "save-all"
tar -cvpzf /opt/minecraft/backups/server-$(date +%F_%R).tar.gz /opt/minecraft/server
rcon "save-on"
## Delete older backups
find /opt/minecraft/backups/ -type f -mtime +7 -name '*.gz' -delete
添加执行权限
chmod +x /opt/minecraft/tools/backup.sh
创建定时任务
crontab -e
设置每日0点自动备份
0 0 * * * /opt/minecraft/tools/backup.sh
5. 解决内存溢出问题
难顶啊,玩着玩着进程就挂了,去看错误日志,看到一个Out of memory
果断百度解决办法,搜到几种优化方法:
更换虚拟机:我换了zulu,效果不好,还是会内存溢出
修改jvm启动参数:-XX:+AggressiveOpts -XX:+UseCompressedOops,效果也不好 这篇文章有说原因
减少server.properties中配置项view-distance:这个我改了之后内存占用好像是减少了一些,但是效果不明显
我又回去看了眼错误日志,人家好像告诉了我们可能的解决办法:
第二条增加物理内存或者swap空间,物理内存要加钱的,swap空间好像听说过但是不知道具体是啥,其实就是利用磁盘来充当内存,从而缓解内存不足的问题
用命令查看系统中已经配置的swap
swapon -s
输入命令显示我系统中没有配置好的swap分区或swap文件
果断添加swap文件
su
cd /var
dd if=/dev/zero of=swapfile bs=1M count=2048
mkswap swapfile
swapon swapfile
echo "/var/swapfile swap swap defaults 0 0" >> /etc/fstab
完成这番操作之后感觉没那么容易内存溢出了
但是为了保险起见,可以编写一个进程挂了自动重启的脚本
~/tools/auto_restart/work.sh
#!/bin/bash
# mutex file
#
# Open a mutual exclusion lock on the file, unless another process already owns one.
#
# If the file is already locked by another process, the operation fails.
# This function defines a lock on a file as having a file descriptor open to the file.
# This function uses FD 9 to open a lock on the file. To release the lock, close FD 9:
# exec 9>&-
#
# From https://stackoverflow.com/questions/185451/quick-and-dirty-way-to-ensure-only-one-instance-of-a-shell-script-is-running-at
mutex() {
local file=$1 pid pids
exec 9>>"$file"
{ pids=$(fuser -f "$file"); } 2>&- 9>&-
for pid in $pids; do
[[ $pid = $$ ]] && continue
exec 9>&-
return 1 # Locked by a pid.
done
}
# Check lock
mutex /opt/minecraft/tools/auto_restart/auto_restart.lock || { echo "auto_restart.sh already running." >&2; exit 1; }
# Restart server
while true;do
if [ `ps -ef | grep server.jar | grep -v grep | wc -l` = 0 ];then
source /opt/minecraft/tools/start_server.sh >&2
echo [`date +%Y-%m-%d` `date +%H:%M:%S`]: restart server >&2
fi
sleep 5
done
脚本里参考stackoverflow上的大佬加了一把锁,防止这个脚本被执行多次同时产生多个实例。
~/tools/auto_restart/auto_restart_on.sh
#!/bin/bash
LOG_FILE="/opt/minecraft/tools/auto_restart/restart.log"
nohup /opt/minecraft/tools/auto_restart/work.sh > $LOG_FILE 2>&1 &
echo auto restart on, view $LOG_FILE to know more.
开启自动重启的脚本,创建后台执行
~/tools/auto_restart/auto_restart_off.sh
#!/bin/bash
kill -9 $(ps -aux | grep work.sh | grep -v grep | awk '{print $2}')
echo auto restart off.
关闭自动重启的脚本,直接kill掉,很粗暴
ok,现在应该可以愉快玩耍了,如果还出现问题可能还会继续更新,如果本文有错误欢迎指出!
2021.10.04 更新
现在服务器已经稳定跑了一个多月没挂了
就是去冒险的时候移动速度过快(开船)可能会导致服务器overloaded,就会变卡
不过不会直接宕掉
整体体验还行
2021.10.23 更新
使用swap空间感觉治标不治本,玩家相距比较远的时候还是会卡,最终还是妥协了,升级了2核4G,玩完mc还可以开新坑(terraria或者饥荒什么的)
参考资料:
https://www.myfreax.com/how-to-install-minecraft-server-on-centos-7/
https://www.bilibili.com/read/cv9784699
https://segmentfault.com/a/1190000008125116
https://stackoverflow.com/questions/185451/quick-and-dirty-way-to-ensure-only-one-instance-of-a-shell-script-is-running-at