Minecraft Blogs / Tutorial

Automatically start and stop (!) a server when nobody's playing - updated

  • 3,906 views, 1 today
  • 3
  • 0
  • 1
UncleGus avatar UncleGus
Level 8 : Apprentice Miner
0
I tried to post this as a comment on this blog but the post is timing out, so I'm posting it here as a new blog. Here is my comment:

Okay, I registered an account so that I could comment on this post. First of all, thank you for posting this! It was exactly what I was looking for. I don't care about server memory or anything like that, but I am running a Terrafirmacraft server, which updates the world based on time lapse, so it's not enough just to have chunks unloaded from memory. It also has seasons, so I don't want to log off in the middle of summer and come back to a cold winter with all my crops dead.

These scripts didn't work straight off the bat; this post is four years old, so lots of things are out of date. That's why I am posting this. I have spent several hours reverse engineering these commands to find out what they do and re-engineering them with up-to-date equivalents, while learning Linux (!!!) along the way. Before reading this, all I knew how to do in Linux was log in and run a script to get Minecraft running. I didn't even know how to stop it! If I wanted to stop it, I had to reboot the whole server.

So here is my version, for anyone else wanting to do the same thing:

Overview
What we're going to do is:
  1. Set up a webservice to listen on the default Minecraft port of 25565 and run a script when it hears something
  2. Create a script that the webservice will invoke that will check if the server is running or not, and start it if it isn't
  3. Set up a timer job to run every X minutes and invoke another script
  4. Create a script that the timer job will run that will check if there are any players on the server, and if not, shut it down

Setting up the webservice
For this you need xinetd installed. Try running it from the command line; if it isn't there, it will tell you how to install it. Create a file /etc/xinetd.d/minecraft:

service minecraft
{
disable = no
type = UNLISTED
port = 25565
socket_type = stream
protocol = tcp
user = root
wait = no
server = /home/UncleGus/bukkit/start.sh
max_load = 20.0
}

Change the server folder to point to your minecraft directory.
What this does is listen on port 25565 and run start.sh when it hears something. I don't know if it runs every time it hears something, but the way I have set it up, it doesn't matter. To get this service running, you will need to restart the xinetd daemon. This will happen at a reboot, but if you want to restart it now, you can with:
$ sudo service xinetd restart

Creating the start script
In your minecraft folder, create a file called start.sh with:

#!/bin/bash
cd "$(dirname "$0")"

# set these variables to what they need to be
RUN="forge-1.7.10-10.13.4.1614-1.7.10-universal.jar"
USERNAME="root"
MINMEM="256M"
MAXMEM="1280M"

# this line checks if java is running
if ! pgrep -f "$RUN" > /dev/null ; then
# this line starts a new screen session called minecraft and runs the .jar file in it
screen - dmS minecraft sudo -u "$USERNAME" -- /usr/bin/java -XX:ParallelGCThreads=2 -Djava.net.preferIPv4Stack=true -Xmx$MAXMEM -Xms$MINMEM -jar "$RUN"

Note the changes here. I found that even when I ran java as my own user, the java processes still ran as root, so checking for java processes run by myself didn't trigger. Also, the screen session didn't seem to run in such a way that the stop script could talk to it unless I used root here. I'm a total Linux noob so I've probably done something wrong here and my server is totally insecure and you can probably hack in and have your way with my tiny azure server running nothing but minecraft. Knock yourself out. I also removed everything to do with running nc and forwarding ports; more about that later. Also, those echo statements didn't work and weren't necessary.

Setting up the timer job
Linux has a list of timer jobs in a table (basically just a file) called crontab. If you type:
$ crontab -e
You will be able to edit this table of jobs. The way it works is you define the time pattern and the command as follows:
MIN HOUR DAYOFMONTH MONTH DAYOFWEEK COMMAND
So something like "15 4 12 3 * echo Hi" would output "Hi" at 4:15am on the 12th of March. There are certain commands for repeating jobs etc. So add:
*/1 * * * * sudo /home/UncleGus/bukkit/stop.sh
to the bottom, changing the directory to where your minecraft server is located. */1 means every minute. This will take effect the next time you restart your server. Note the sudo. Probably very bad practice, but I found that without it, the process could not find the screen session.

Creating the timer job script to stop the server
In your minecraft folder, create a file called stop.sh with:
#!/bin/bash

cd $(dirname $0)
scan=minecraft
pl() {
screen -S $scan -p 0 -X stuff '/list\n'
echo $(tail -n 1 /home/UncleGus/bukkit/logs/latest.log | wc -m)
}

[ $(pl) -lt 35 ] && {
echo "No players connected, waiting for three minutes"
sleep 180
[ $(pl) -lt 35 ] && {
echo "Still no players connected, shutting down"
screen -S $scan -p 0 -X stuff '/stop\n'
}
}

What this does in the pl() function is find the first screen session called minecraft and "stuff" a command into it of "/list" (in the original, the command was "who\015" but the who command doesn't work and the \0 was misplaced. \015 is the same as \n, the newline character).
It then counts the number of characters on the last line of the server log (note the different location for the log file now). If there are no players, the count will be 34. If there are players, the count will be higher. So this script runs pl() and if there are less than 35 characters, it will wait for three minutes (in case people haven't had a chance to join yet) and then check again and send the "/stop" command if there are still no players.

Don't forget to sudo chmod +x your script files so that they can actually be executed as scripts.

Regarding the port forwarding, nc seems to have changed since this article was written. I did manage to get the port forwarding working once using nc.traditional, but I decided against using it in the end. My reasoning:
  1. I don't know if the start.sh script is run every time the webservice hears something on port 25565. If it does, this could be a bit messy if players are connecting over 25565.
  2. I only got it working once.
  3. If you have 25565 forwarded to 25555 on the server, then every time someone opens their multiplayer screen and queries the server on 25565, it will wake it up, even if they aren't intending to join it. By leaving it separate, you can have players add the server to their list, using port 25555, and when they want to wake the server up, they can attempt to direct connect to the server address without specifying the port. It will fail, but the attempt will invoke the wake up routine. Then they can just refresh their server list until the 25555 server is up.
I hope someone else finds this helpful, I certainly learned a lot and am enjoying having my on-demand TFC server.
Creditkjoe
Tags

Create an account or sign in to comment.

1
09/03/2019 12:42 pm
Level 17 : Journeyman Farmer
The Wub Munzta
The Wub Munzta avatar
This was really helpful for me on my linux installation. Unfortunately I have another server with Windows on it and tried using cygwin to follow this but that didn't work. I did find software that works on Linux, Mac, and Windows though! The applications that I found are named McMyAdmin or AMP, they are both by the same developers but AMP costs ~$10 currently. The functionality added in AMP is worth it in my opinion but is a nightmare to learn how to set up. Both of the programs support sleeping and wake up on either a ping or when someone tries to join.
Planet Minecraft

Website

© 2010 - 2023
www.planetminecraft.com

Welcome