Minecraft server startup/shutdown with systemd

After browsing through the manpages few more times (yeah, the answer is never there the first time...), I've come up with a solution... which did not work. After browsing even more, I've finally come up with the most elegant solution possible.

[Unit]
Description=Minecraft server
After=local-fs.target network.target

[Service]
WorkingDirectory=/home/minecraft/minecraft_server
User=minecraft
Group=minecraft
Type=forking
# Run it as a non-root user in a specific directory

ExecStart=/usr/bin/screen -h 1024 -dmS minecraft ./minecraft_server.sh
# I like to keep my commandline to launch it in a separate file
# because sometimes I want to change it or launch it manually
# If it's in the WorkingDirectory, then we can use a relative path

# Send "stop" to the Minecraft server console
ExecStop=/usr/bin/screen -p 0 -S minecraft -X eval 'stuff \"stop\"\015'
# Wait for the PID to die - otherwise it's killed after this command finishes!
ExecStop=/bin/bash -c "while ps -p $MAINPID > /dev/null; do /bin/sleep 1; done"
# Note that absolute paths for all executables are required!

[Install]
WantedBy=multi-user.target

This really does look better than my original script! However, there are a few regressions.

  • If I want to pass commands to the server console, then I'll have to make a separate script to do it.
  • After running systemctl start minecraft or systemctl stop minecraft, be sure to check systemctl status minecraft, because those commands give no output at all, even if they actually fail. This is the only major regression compared to scripts - "always examine your output" is #1 rule in IT, but systemd doesn't seem to care about it...
  • Also, I expected systemd to be able to manage the service shutdown without the "wait for the PID to die" workaround. In the old init script, I had to do this manually, because it was a script, and systemd is trying to eliminate the need for complex scripts that to the same things; it eliminates the need to manually script in all the timeouts and killing whoever did not die, but "waiting for the pid to die" is the next most common thing, and we still need to script it.