Autopause functionality (#531)

This commit is contained in:
Michael Kirsch
2020-05-20 15:17:58 +02:00
committed by GitHub
parent ede58d9159
commit 71a7afab17
13 changed files with 324 additions and 10 deletions
+97
View File
@@ -0,0 +1,97 @@
#!/bin/bash
exec 1>/tmp/terminal-mc
. /autopause/autopause-fcns.sh
sudo /usr/sbin/knockd -c /autopause/knockd-config.cfg -d
if [ $? -ne 0 ] ; then
while :
do
if [[ -n $(ps -o comm | grep java) ]] ; then
break
fi
sleep 0.1
done
echo "[Autopause loop] Failed to start knockd daemon."
echo "[Autopause loop] Possible cause: docker's host network mode."
echo "[Autopause loop] Recreate without host mode or disable autopause functionality."
echo "[Autopause loop] Stopping server."
killall -SIGTERM java
exit 1
fi
STATE=INIT
while :
do
case X$STATE in
XINIT)
# Server startup
if mc_server_listening ; then
TIME_THRESH=$(($(current_uptime)+$AUTOPAUSE_TIMEOUT_INIT))
echo "[Autopause loop] MC Server listening for connections - stopping in $AUTOPAUSE_TIMEOUT_INIT seconds"
STATE=K
fi
;;
XK)
# Knocked
if java_clients_connected ; then
echo "[Autopause loop] Client connected - waiting for disconnect"
STATE=E
else
if [[ $(current_uptime) -ge $TIME_THRESH ]] ; then
echo "[Autopause loop] No client connected since startup / knocked - stopping"
/autopause/pause.sh
STATE=S
fi
fi
;;
XE)
# Established
if ! java_clients_connected ; then
TIME_THRESH=$(($(current_uptime)+$AUTOPAUSE_TIMEOUT_EST))
echo "[Autopause loop] All clients disconnected - stopping in $AUTOPAUSE_TIMEOUT_EST seconds"
STATE=I
fi
;;
XI)
# Idle
if java_clients_connected ; then
echo "[Autopause loop] Client reconnected - waiting for disconnect"
STATE=E
else
if [[ $(current_uptime) -ge $TIME_THRESH ]] ; then
echo "[Autopause loop] No client reconnected - stopping"
/autopause/pause.sh
STATE=S
fi
fi
;;
XS)
# Stopped
if rcon_client_exists ; then
/autopause/resume.sh
fi
if java_running ; then
if java_clients_connected ; then
echo "[Autopause loop] Client connected - waiting for disconnect"
STATE=E
else
TIME_THRESH=$(($(current_uptime)+$AUTOPAUSE_TIMEOUT_KN))
echo "[Autopause loop] Server was knocked - waiting for clients or timeout"
STATE=K
fi
fi
;;
*)
echo "[Autopause loop] Error: invalid state: $STATE"
;;
esac
if [[ "$STATE" == "S" ]] ; then
# before rcon times out
sleep 2
else
sleep $AUTOPAUSE_PERIOD
fi
done
+38
View File
@@ -0,0 +1,38 @@
#!/bin/bash
current_uptime() {
echo $(awk '{print $1}' /proc/uptime | cut -d . -f 1)
}
java_running() {
[[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]]
}
rcon_client_exists() {
[[ -n "$(ps -a -o comm | grep 'rcon-cli')" ]]
}
mc_server_listening() {
[[ -n $(netstat -tln | grep "0.0.0.0:$SERVER_PORT" | grep LISTEN) ]]
}
java_clients_connected() {
local connections
connections=$(netstat -tn | grep ":$SERVER_PORT" | grep ESTABLISHED)
if [[ -z "$connections" ]] ; then
return 1
fi
IFS=$'\n'
connections=($connections)
unset IFS
# check that at least one external address is not localhost
# remember, that the host network mode does not work with autopause because of the knockd utility
for (( i=0; i<${#connections[@]}; i++ ))
do
if [[ ! $(echo "${connections[$i]}" | awk '{print $5}') =~ ^\s*127\.0\.0\.1:.*$ ]] ; then
# not localhost
return 0
fi
done
return 1
}
+12
View File
@@ -0,0 +1,12 @@
[options]
logfile = /dev/null
[unpauseMCServer-server]
sequence = 25565
seq_timeout = 1
command = /sbin/su-exec minecraft:minecraft /autopause/resume.sh
tcpflags = syn
[unpauseMCServer-rcon]
sequence = 25575
seq_timeout = 1
command = /sbin/su-exec minecraft:minecraft /autopause/resume.sh
tcpflags = syn
+19
View File
@@ -0,0 +1,19 @@
#!/bin/bash
if [[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]] ; then
# save world
rcon-cli save-all >/dev/null
# wait until mc-monitor is no longer connected to the server
while :
do
if [[ -z "$(netstat -nt | grep "127.0.0.1:$SERVER_PORT" | grep 'ESTABLISHED')" ]]; then
break
fi
sleep 0.1
done
# finally pause the process
echo "[$(date -Iseconds)] [Autopause] Pausing Java process" >/tmp/terminal-mc
killall -q -STOP java
fi
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
if [[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^T.*$ ]] ; then
echo "[$(date -Iseconds)] [Autopause] Knocked, resuming Java process" >/tmp/terminal-mc
killall -q -CONT java
fi
+2
View File
@@ -0,0 +1,2 @@
%minecraft ALL=(ALL) NOPASSWD:/usr/bin/killall
%minecraft ALL=(ALL) NOPASSWD:/usr/sbin/knockd