How to control systemd service using screen?

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

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x