I’ve set up a systemd service to run my Minecraft server. Now, I need it to repeat the start script when the server crashes.
Here’s my code so far:
#!/bin/bash
while true; do
cd /home/mcserver/Spigot
echo Starting Spigot...
echo 600 > ./restart-info
java -jar spigot.jar
echo Server has stopped or crashed, starting again in 5 minutes...
sleep 300
done
I can actually view the output of spigot.jar using systemctl status spigot, but I also want to control the server console, maybe using screen.
When I try to do this:
screen -S "Spigot" java -jar spigot.jar
I’ll get the Must be connected to a terminal error. This command only works in a terminal (not in a script) and I can attach it using screen -r.
Is there any way to “bypass” this screen bug?
I already tried to place script /dev/null before the screen command.
I don’t want to use screen with -d and -m because it’ll run in the background and the script will keep restarting my server.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
I suspect you’ve stumbled on this blog post which uses screen to solve a problem where your minecraft server stops when you $ java -jar spigot.jar, then close your ssh or putty session. That method seems to have become the cannonical answer as to how to run a minecraft server, even though it isn’t necessary.
systemd is a totally different (and better) solution to this problem, circumventing the need for screen. You can achieve everything you’ve done in your script with systemd service options.
To run a vanilla minecraft server, create /etc/systemd/system/minecraft.service with this content:
[Unit] Description=Minecraft Server [Service] Type=simple WorkingDirectory=/home/minecraft ExecStart=java -Xmx1024M -Xms1024M -jar /home/minecraft/server.jar nogui User=minecraft Restart=on-failure [Install] WantedBy=multi-user.target
Set it to launch automatically after boot with systemctl enable minecraft.
You asked about how to control it:
$ sudo systemctl start minecraft # Starts the service if it wasn't running $ sudo systemctl stop minecraft # Stops the service $ sudo systemctl restart minecraft # Restarts the service $ sudo systemctl status minecraft # Find out how the service is doing $ sudo journalctl -u minecraft -f # Monitor the logs
This does everything except give you a means to send commands to the console to do that, we’ll set up a file that the server will listen to where you can write your commands by creating the following systemd units:
/etc/systemd/system/minecraft.socket:
[Unit] PartOf=minecraft.service [Socket] ListenFIFO=%t/minecraft.stdin
and /etc/systemd/system/minecraft.service:
[Unit] Description=Minecraft Server [Service] Type=simple WorkingDirectory=/home/minecraft ExecStart=java -Xmx1024M -Xms1024M -jar /home/minecraft/server.jar nogui User=minecraft Restart=on-failure Sockets=minecraft.socket StandardInput=socket StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
Now you can send console commands by echoing stuff into that file:
echo "help" > /run/minecraft.stdin echo "/stop" > /run/minecraft.stdin
What’s also cool is that you can make your own custom sequences of commands and cat the entire file into the console. For example, if you play UHC, you can start a new world, have people log-in, then cat uhc.commands > /run/minecraft.stdin to set the gamerules, spread the players, and start the event.
Method 2
I don’t want to use screen with -d and -m because it’ll run in the background and the script will keep restarting my server.
So use -D instead of -d (note the capital case!)
-D -m This also starts screen in “detached” mode, but doesn’t fork a
new process. The command exits if the session terminates.
As screen won’t fork a new process, it will block while java is running, and exit when the server stops.
As a bonus, if you add -S spigot you can monitor the output (and even send commands!) from any terminal by attaching to that screen
And… since you’re using a systemd service anyway (and you should indeed), why are you doing this restart loop in your script? Let systemd handle that for you using Restart=always and RestartSec=5min
Method 3
I’ve found a solution for this, but I won’t be able to view output using systemctl status spigot.
#!/bin/bash
while true; do
cd /home/mcserver/Spigot
echo Starting Spigot...
screen -d -m -S Spigot java -jar spigot.jar
SCREEN_NAME="Spigot"
while screen -list | grep -q $SCREEN_NAME
do
sleep 1
done
echo Server has stopped, starting again in 5 minutes...
sleep 300
done
This script will wait until the screen session terminates. I can now view the output or interact with the console using screen -r or if I have multiple screen sessions running, I can attach using screen -D -R "Spigot".
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0