-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Autopause functionality #531
Changes from 29 commits
2e2c883
e77fae6
51d73a5
e52ec31
6ce10c3
1606223
424651c
fb74035
6a4807a
b7f1a25
dcc6a71
bafd8e3
1a1eaa3
6b0e663
6a3cdfc
3193ffa
8830498
6652add
5e8b5f1
092258c
356c103
a550427
65c5fb2
9bf3d42
801b53d
9ca44d0
df6ff76
79d5e5b
31fc35e
053b0eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
#!/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=K | ||
TIME_THRESH=$(($(current_uptime)+$AUTOPAUSE_TIMEOUT_KN)) | ||
|
||
while : | ||
do | ||
case X$STATE in | ||
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 - stopping" | ||
/autopause/pause.sh | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This scenario seemed a bit too "aggressive". I would start up a fresh server (which can take 60+ seconds) and almost immediately it would pause:
Would it make sense to have an extra allowance for this startup time threshold? Or would increasing the default for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about check for a specific file before enabling auto pause, like level.dat or something, should only be there when map is finish generated? or parse log for [Server thread/INFO]: Done There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, parsing the log in the data directory is possible, but we'd have to parse for something in every version. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can only say for vanilla I dont like fixed timeouts because for very slow or very fast hosts its not good... (not that i think that its that big of a problem anyway) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @eihns I was thinking more in the Minecraft versions, e.g. Vanilla 1.3 only prints:
which would fail your match, whereas my forge 1.7.10 prints (when searching for Done):
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dont know what you mean, both print some sort of done when finish? Cant we just search for * done * ? - even if it starts on a done some seconds too early, better then hard coding, i guess?! Bc whatever happens the world will be generated at this point... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I opted for the new environment variable, specifying TO after the server starts listening |
||
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#!/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')" ]] | ||
} | ||
|
||
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 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
%minecraft ALL=(ALL) NOPASSWD:/usr/bin/killall | ||
%minecraft ALL=(ALL) NOPASSWD:/usr/sbin/knockd |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#!/bin/bash | ||
|
||
. /start-utils | ||
|
||
if isTrue "${ENABLE_AUTOPAUSE}" && [[ "$( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }')" =~ ^T.*$ ]]; then | ||
echo "Java process suspended by Autopause function" | ||
exit 0 | ||
else | ||
mc-monitor status --host localhost --port $SERVER_PORT | ||
exit $? | ||
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious what this is doing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redirects stdout to the terminal, that is logged by docker, as this script is called detached