Instalacja
Z poziomu roota instalujemy program screen:
apt install screen
Tworzymy użytkownik pod Minecrafta:
useradd -m -s /bin/bash minecraft
Z poziomu zwykłego użytkownika ściągamy Javę 64biotwą pod system Linux (https://www.oracle.com/java/technologies/java-se-glance.html):
wget https://download.oracle.com/java/24/latest/jdk-24_linux-x64_bin.tar.gz
Rozpakowujemy poleceniem:
tar xzf ./jdk-24_linux-x64_bin.tar.gz
Tworzymy link symboliczny do Javy:
ln -s /home/minecraft/jdk-24.0.2 /home/minecraft/java
Ściągamy Minecrafta z trony: https://www.minecraft.net/pl-pl/download/server i uploadujemy na serwer plik jar do katalogu /home/minecraft/jar – głównie dla porządku bo z czasem może zajść potrzeba aktualizacji. Tworzymy symboliczny link do pliku jar:
ln -s /home/minecraft/jar/minecraft_server.1.21.4.jar /home/minecraft/minecraft_server.jar
Pierwsze uruchomienie
Uruchamiamy poleceniem:
${HOME}/java/bin/java -Xms1G -Xmx2G -jar /home/minecraft/minecraft_server.jar nogui
Powinno zakończyć się błędem:
Starting net.minecraft.server.Main
[16:38:07] [ServerMain/ERROR]: Failed to load properties from file: server.properties
java.nio.file.NoSuchFileException: server.properties
at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92) ~[?:?]
at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106) ~[?:?]
at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) ~[?:?]
at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:262) ~[?:?]
at java.base/java.nio.file.Files.newByteChannel(Files.java:380) ~[?:?]
at java.base/java.nio.file.Files.newByteChannel(Files.java:432) ~[?:?]
at java.base/java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:420) ~[?:?]
at java.base/java.nio.file.Files.newInputStream(Files.java:160) ~[?:?]
at apy.b(SourceFile:62) ~[server-1.21.4.jar:?]
at apv.a(SourceFile:141) ~[server-1.21.4.jar:?]
at apw.<init>(SourceFile:12) ~[server-1.21.4.jar:?]
at net.minecraft.server.Main.main(SourceFile:116) ~[server-1.21.4.jar:?]
at net.minecraft.bundler.Main.lambda$run$0(Main.java:54) ~[?:?]
at java.base/java.lang.Thread.run(Thread.java:1575) [?:?]
[16:38:07] [ServerMain/WARN]: Failed to load eula.txt
[16:38:07] [ServerMain/INFO]: You need to agree to the EULA in order to run the server. Go to eula.txt for more info.
Utworzyło nam dwa pliki: /home/minecraft/eula.txt oraz /home/minecraft/server.properties. Edytujemy ten pierwszy plik i modyfikujemy w nim linie elua:
eula=true
Konfiguracja
Edytujemy plik /home/minecraft/server.properties i zmieniamy go pod własne potrzeby. Opis opcji można znaleźć tu: https://minecraft.fandom.com/wiki/Server.properties
Skrypt startowy:
#!/bin/bash
if [ -f ${HOME}/pid ];
then
PID=`cat ${HOME}/pid`
if ps -p $PID > /dev/null
then
echo "Minecraft server is already running!"
exit
fi
fi
echo -n "Start Minectraft server... "
screen -S minecraft -d -m ${HOME}/java/bin/java -Xms1G -Xmx2G -jar /home/minecraft/minecraft_server.jar nogui --pidFile ${HOME}/pid
echo "OK"
Skrypt stopujący:
#!/bin/bash
if [ -f ${HOME}/pid ];
then
PID=`cat ${HOME}/pid`
if ps -p $PID > /dev/null
then
echo -n "Shutdown Minecraft server... "
screen -S minecraft -X stuff '/stop'`echo -ne '\015'`
echo "OK"
fi
else
echo "Minecraft server is not running!"
fi
Minecraft wykorzystuje port 25565 UDP i TCP.
Pliki konfiguracyjne dla services, aby serwer Minecrafta startował po uruchomieniu się. Pierwszy plik: /etc/systemd/system/minecraft.service:
[Unit]
Description=My Service
After=network.target
[Service]
User=minecraft
Group=minecraft
WorkingDirectory=/home/minecraft
Type=simple
KillSignal=SIGCONT
Sockets=minecraft.socket
ExecStart=/bin/sh -c "/home/minecraft/java/bin/java -Xms1G -Xmx2G -jar /home/minecraft/minecraft_server.jar nogui --pidFile /home/minecraft/pid < /run/minecraft.control"
ExecStop=/bin/sh -c "echo /stop > /run/minecraft.control"
RestartSec=15
Restart=on-failure
[Install]
WantedBy=multi-user.target
Drugi plik: /etc/systemd/system/minecraft.socket:
[Unit]
BindsTo=minecraft.service
[Socket]
ListenFIFO=/run/minecraft.control
FileDescriptorName=control
RemoveOnStop=true
SocketMode=0660
SocketUser=minecraft
SocketGroup=minecraft
Należy przeładować systemd:
systemctl daemon-reload
Teraz możemy operować z poziomu systemud. Start:
service minecraft start
Stop:
service minecraft stop
Status:
service minecraft status
Kopia zapasowa
Tworzymy katalogi:
mkdir -p /home/minecraft/backup/hours
mkdir /home/minecraft/backup/days
Przykładowy skrypt /home/minecraft/backup.sh:
#!/bin/bash
if [ -f ${HOME}/pid ];
then
PID=`cat ${HOME}/pid`
if ps -p $PID > /dev/null
then
echo "/time query gametime" > /run/minecraft.control
sleep 1
lastTimeGame="`cat /home/minecraft/logs/latest.log | grep \"The time is\" | tail -1 | awk '{print $7}'`"
lastTimeFile="`cat /home/minecraft/lasttime.txt`"
if [ "$lastTimeGame" != "$lastTimeFile" ];
then
echo "$lastTimeGame" > /home/minecraft/lasttime.txt
file7z="${HOME}/backup/hours/minecraft_`date '+%Y%m%d_%H%M'`.7z"
7za a ${file7z} ${HOME}/logs ${HOME}/world ${HOME}/*.sh ${HOME}/*.json ${HOME}/*.txt ${HOME}/server.properties
file7zday="${HOME}/backup/days/minecraft_`date '+%m%d'`.7z"
cp ${file7z} ${file7zday}
find ${HOME}/backup/hours/minecraft_*.7z -mtime +14 -type f -exec rm {} \;
fi
fi
fi
Dodajemy wpis do crontaba
crontab -e
Wpis:
15 * * * * /home/minecraft/backup.sh > /dev/null
Powyższy skrypt będzie robił co godzinę kopię zapasową Minecrafta, ale tylko wtedy gdy ktoś będzie grał. Kopia będzie w katalogu /home/minecraft/backup/hours (trzymana przez dwa tygodnie) oraz ostatnia dzienna trzymana przez rok w katalogu: /home/minecraft/backup/hours.