Last active
July 30, 2023 15:25
-
-
Save carchrae/3dc0da023c8e9bb36441dcd439950870 to your computer and use it in GitHub Desktop.
stop (pause) inactive minecraft server process
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# /home/minecraft/bin/minecraft-sleep.sh | |
#set -v | |
cd "$(dirname "$0")" | |
# service name (i'm using systemd) | |
SERVICE_NAME="$1" | |
# set this to the port your minecraft server is on | |
#PORT=25565 | |
PORT=`grep server-port ../$SERVICE_NAME/server.properties | cut -d '=' -f2` | |
# delay before starting | |
START_DELAY=600 | |
# how frequently do we check for connections (seconds) | |
CHECK_DELAY=600 | |
# script will start the server briefly duing each cycle | |
POLL_CYCLE=20 | |
# how long to resume server during poll cycle | |
POLL_RUN=1 | |
# delay in checking for connections during poll | |
POLL_DELAY=1 | |
# maybe you want to customise this, eg if not using systemd | |
function find_pid(){ | |
echo $(ps -o 'pid,ppid,args,unit' `pgrep java` | grep $SERVICE_NAME | xargs | cut -d ' ' -f1) | |
} | |
function pause(){ | |
# this stops the process (like ctrl-z) | |
PID=$(find_pid) | |
if [ -n "$PID" ]; then | |
kill -STOP $PID | |
else | |
echo "could not find PID" | |
fi | |
} | |
function resume(){ | |
PID=$(find_pid) | |
if [ -n "$PID" ]; then | |
kill -CONT $PID | |
else | |
echo "could not find PID" | |
fi | |
} | |
resume | |
sleep $START_DELAY | |
while true; do | |
# wait a bit before looping again | |
sleep 120 | |
# some random so processes don't wake up all at the same time | |
sleep $[ ( $RANDOM % 10 ) + 1 ]s | |
echo "checking for activity on $PORT" | |
# while ( netstat -tn | grep $PORT | grep ESTABLISHED ); do | |
while ( netstat -tn | grep $PORT ); do | |
#echo "still active..." | |
sleep $CHECK_DELAY | |
done | |
echo "no active connections on $PORT, so pausing process $(find_pid)" | |
pause | |
echo "waiting for activity on $PORT, will run server for $POLL_RUN seconds every $POLL_CYCLE seconds." | |
ACTIVE="" | |
while [ -z "$ACTIVE" ]; do | |
#echo "Resume process $(find_pid) for $POLL_RUN seconds to prevent crashes/timeouts" | |
resume | |
sleep $POLL_RUN | |
pause | |
#echo "waiting for activity on $PORT" | |
POLL_UNTIL=$((SECONDS+POLL_CYCLE)) | |
while [ $SECONDS -lt $POLL_UNTIL ]; do | |
ACTIVE=`netstat -tn | grep $PORT` | |
#echo "ACTIVE=$ACTIVE" | |
if [ -n "$ACTIVE" ]; then | |
break | |
else | |
sleep $POLL_DELAY | |
fi | |
done | |
done; | |
echo "Resuming process $(find_pid) due to activty $ACTIVE" | |
resume | |
done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# /home/minecraft/bin/minecraft-wake.sh | |
## this just pokes the port of a minecraft instance, making it wake up. equivalent to `resume` in minecraft-sleep.sh | |
## you might want to use this if you have some scripts that run, eg backups, that need the server responding | |
## as if a user was logged in | |
cd "$(dirname "$0")" | |
#set -v | |
# service name (i'm using systemd) | |
SERVICE_NAME="$1" | |
# set this to the port your minecraft server is on | |
#PORT=25565 | |
PORT=`grep server-port ../$SERVICE_NAME/server.properties | cut -d '=' -f2` | |
echo "boop" | nc -q 3 localhost $PORT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# /etc/systemd/system/[email protected] | |
# this is a systemd service, use start and/or enable (over reboots) | |
# presumes that minecraft runs as a restricted user 'minecraft' | |
[Unit] | |
Description=Minecraft Server: %i | |
After=network.target | |
[Service] | |
WorkingDirectory=/home/minecraft/%i | |
User=minecraft | |
Group=minecraft | |
Restart=always | |
ExecStartPre=/home/minecraft/bin/start-minecraft-sleep.sh %i | |
ExecStart=/usr/bin/screen -DmS mc-%i /home/minecraft/%i/start.sh | |
ExecStop=/home/minecraft/bin/stop-minecraft-sleep.sh %i || true | |
ExecStop=/bin/sleep 3 | |
ExecStop=/usr/bin/screen -p 0 -S mc-%i -X eval 'stuff "say SERVER SHUTTING DOWN IN 15 SECONDS..."\015' || true | |
ExecStop=/bin/sleep 5 | |
ExecStop=/usr/bin/screen -p 0 -S mc-%i -X eval 'stuff "say SERVER SHUTTING DOWN IN 10 SECONDS..."\015' || true | |
ExecStop=/bin/sleep 5 | |
ExecStop=/usr/bin/screen -p 0 -S mc-%i -X eval 'stuff "say SERVER SHUTTING DOWN IN 5 SECONDS..."\015' || true | |
ExecStop=/bin/sleep 5 | |
ExecStop=/usr/bin/screen -p 0 -S mc-%i -X eval 'stuff "save-all"\015' || true | |
ExecStop=/usr/bin/screen -p 0 -S mc-%i -X eval 'stuff "stop"\015' || true | |
[Install] | |
WantedBy=multi-user.target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# /home/minecraft/bin/start-minecraft-sleep.sh | |
cd "$(dirname "$0")" | |
# the gawk is to add timestamps | |
./minecraft-sleep.sh $1 | gawk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0 }' >> ../$1/logs/sleep.log & | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# /home/minecraft/bin/stop-minecraft-sleep.sh | |
cd "$(dirname "$0")" | |
#set -v | |
SERVICE_NAME=$1 | |
# maybe you want to customise this, eg if not using systemd | |
function find_pid(){ | |
echo $(ps -o 'pid,ppid,args,unit' `pgrep java` | grep $SERVICE_NAME | cut -d ' ' -f1) | |
} | |
function resume(){ | |
PID=$(find_pid) | |
if [ -n "$PID" ]; then | |
kill -CONT $PID | |
else | |
echo "could not find PID" | |
fi | |
} | |
echo "stopping minecraft-sleep.sh" | |
pkill -f "bin/minecraft-sleep.sh $1" || true | |
sleep 1 | |
echo "resuming process $(find_pid)" | |
resume |
glad it was of help. and i'm not sure this is my most elegant code - but is bash ever elegant!? :D
and indeed, adapt to fit. that is what i did based on michiel's code. i just had to generalise it a bit, since i am running three servers on the same box, and knockd seemed like overkill.
as an aside, i looked at this briefly too; https://github.com/jkutner/heroku-buildpack-minecraft - which is pretty clever (and free, but low RAM), but convoluted in how it exposes the port using ngrok. in the end, i hosted the minecraft servers on a pc at home, since 512mb isn't enough for a minecraft server unless you run an old version.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
That makes sense. I just incorporated your code as part of my run.sh script when my VPS boots and while looking through the logic I noticed there was no handling of the situation that there was no server actually available. If Minecraft dies on mine for some reason I wanted to script to stop polling. Thanks again! I've got it doing what I need for now. This was a huge help! I was going to write something much less elegant.