Skip to content

Commit 2fb01b4

Browse files
authored
Autopause update: allow network interface selection (#711)
* Cherry-pick: Fixing AUTOPAUSE on Raspberry Pi 4s (#708) * implement autopause interface selection * concentrate ps calls in function file * wording and add note about PAPER's etc watchdogs
1 parent 02bce8c commit 2fb01b4

File tree

8 files changed

+60
-23
lines changed

8 files changed

+60
-23
lines changed

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ ENV UID=1000 GID=1000 \
7474
TYPE=VANILLA VERSION=LATEST FORGEVERSION=RECOMMENDED SPONGEBRANCH=STABLE SPONGEVERSION= FABRICVERSION=LATEST LEVEL=world \
7575
PVP=true DIFFICULTY=easy ENABLE_RCON=true RCON_PORT=25575 RCON_PASSWORD=minecraft \
7676
LEVEL_TYPE=DEFAULT SERVER_PORT=25565 ONLINE_MODE=TRUE SERVER_NAME="Dedicated Server" \
77-
ENABLE_AUTOPAUSE=false AUTOPAUSE_TIMEOUT_EST=3600 AUTOPAUSE_TIMEOUT_KN=120 AUTOPAUSE_TIMEOUT_INIT=600 AUTOPAUSE_PERIOD=10
77+
ENABLE_AUTOPAUSE=false AUTOPAUSE_TIMEOUT_EST=3600 AUTOPAUSE_TIMEOUT_KN=120 AUTOPAUSE_TIMEOUT_INIT=600 \
78+
AUTOPAUSE_PERIOD=10 AUTOPAUSE_KNOCK_INTERFACE=eth0
7879

7980
COPY start* /
8081
COPY health.sh /

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,22 +182,22 @@ healthy
182182

183183
Some orchestration systems, such as Portainer, don't allow for disabling the default `HEALTHCHECK` declared by this image. In those cases you can approximate the disabling of healthchecks by setting the environment variable `DISABLE_HEALTHCHECK` to `true`.
184184

185-
## Autopause (experimental)
185+
## Autopause
186186

187187
### Description
188188

189-
> EXPERIMENTAL: this feature only works with default bridge networking using official Docker distributions. Host networking and container management software, such as Portainer, and NAS solutions do not seem to provide compatible networking.
190-
191189
There are various bug reports on [Mojang](https://bugs.mojang.com) about high CPU usage of servers with newer versions, even with few or no clients connected (e.g. [this one](https://bugs.mojang.com/browse/MC-149018), in fact the functionality is based on [this comment in the thread](https://bugs.mojang.com/browse/MC-149018?focusedCommentId=593606&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-593606)).
192190

193191
An autopause functionality has been added to this image to monitor whether clients are connected to the server. If for a specified time no client is connected, the Java process is stopped. When knocking on the server port (e.g. by the ingame Multiplayer server overview), the process is resumed. The experience for the client does not change.
194192

195193
Of course, even loaded chunks are not ticked when the process is stopped.
196194

197-
From the server's point of view, the pausing causes a single tick to take as long as the process is stopped, so the server watchdog might intervene after the process is continued, possibly forcing a container restart. To prevent this, ensure that the `max-tick-time` in the `server.properties` file is set correctly.
195+
From the server's point of view, the pausing causes a single tick to take as long as the process is stopped, so the server watchdog might intervene after the process is continued, possibly forcing a container restart. To prevent this, ensure that the `max-tick-time` in the `server.properties` file is set correctly. Non-vanilla versions might have their own configuration file, you might have to disable their watchdogs separately (e.g. PAPER Servers).
198196

199197
On startup the `server.properties` file is checked and, if applicable, a warning is printed to the terminal. When the server is created (no data available in the persistent directory), the properties file is created with the Watchdog disabled.
200198

199+
The utility used to wake the server (`knock(d)`) works at network interface level. So the correct interface has to be set using the `AUTOPAUSE_KNOCK_INTERFACE` variable when using non-default networking environments (e.g. host-networking, Portainer oder NAS solutions). See the description of the variable below.
200+
201201
A starting, example compose file has been provided in [examples/docker-compose-autopause.yml](examples/docker-compose-autopause.yml).
202202

203203
### Enabling Autopause
@@ -208,7 +208,7 @@ Enable the Autopause functionality by setting:
208208
-e ENABLE_AUTOPAUSE=TRUE
209209
```
210210

211-
There are 4 more environment variables that define the behaviour:
211+
The following environment variables define the behaviour of auto-pausing:
212212
* `AUTOPAUSE_TIMEOUT_EST`, default `3600` (seconds)
213213
describes the time between the last client disconnect and the pausing of the process (read as timeout established)
214214
* `AUTOPAUSE_TIMEOUT_INIT`, default `600` (seconds)
@@ -217,6 +217,8 @@ describes the time between server start and the pausing of the process, when no
217217
describes the time between knocking of the port (e.g. by the main menu ping) and the pausing of the process, when no client connects inbetween (read as timeout knocked)
218218
* `AUTOPAUSE_PERIOD`, default `10` (seconds)
219219
describes period of the daemonized state machine, that handles the pausing of the process (resuming is done independently)
220+
* `AUTOPAUSE_KNOCK_INTERFACE`, default `eth0`
221+
<br>Describes the interface passed to the `knockd` daemon. If the default interface does not work, run the `ifconfig` command inside the container and derive the interface receiving the incoming connection from its output. The passed interface must exist inside the container. Using the loopback interface (`lo`) does likely not yield the desired results.
220222

221223
## Deployment Templates and Examples
222224

files/autopause/autopause-daemon.sh

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,48 @@
22

33
. /autopause/autopause-fcns.sh
44

5-
. /start-utils
5+
. ${SCRIPTS:-/}start-utils
66

7-
sudo /usr/sbin/knockd -c /tmp/knockd-config.cfg -d
8-
if [ $? -ne 0 ] ; then
7+
8+
autopause_error_loop() {
9+
logAutopause "Available interfaces within the docker container:"
10+
INTERFACES=$(echo /sys/class/net/*)
11+
INTERFACES=${INTERFACES//\/sys\/class\/net\//}
12+
logAutopause " $INTERFACES"
13+
logAutopause "Please set the environment variable AUTOPAUSE_KNOCK_INTERFACE to the interface that handles incoming connections."
14+
logAutopause "If unsure which interface to choose, run the ifconfig command in the container."
15+
logAutopause "Autopause failed to initialize. This log entry will be printed every 30 minutes."
916
while :
1017
do
11-
if [[ -n $(ps -o comm | grep java) ]] ; then
12-
break
13-
fi
14-
sleep 0.1
18+
sleep 1800
19+
logAutopause "Autopause failed to initialize."
1520
done
21+
}
22+
23+
# wait for java process to be started
24+
while :
25+
do
26+
if java_process_exists ; then
27+
break
28+
fi
29+
sleep 0.1
30+
done
31+
32+
# check for interface existence
33+
if [[ -z "$AUTOPAUSE_KNOCK_INTERFACE" ]] ; then
34+
logAutopause "AUTOPAUSE_KNOCK_INTERFACE variable must not be empty!"
35+
autopause_error_loop
36+
fi
37+
if ! [[ -d "/sys/class/net/$AUTOPAUSE_KNOCK_INTERFACE" ]] ; then
38+
logAutopause "Selected interface \"$AUTOPAUSE_KNOCK_INTERFACE\" does not exist!"
39+
autopause_error_loop
40+
fi
41+
42+
sudo /usr/sbin/knockd -c /tmp/knockd-config.cfg -d -i "$AUTOPAUSE_KNOCK_INTERFACE"
43+
if [ $? -ne 0 ] ; then
1644
logAutopause "Failed to start knockd daemon."
17-
logAutopause "Possible cause: docker's host network mode."
18-
logAutopause "Recreate without host mode or disable autopause functionality."
19-
logAutopause "Stopping server."
20-
killall -SIGTERM java
21-
exit 1
45+
logAutopause "Probable cause: Unable to attach to interface \"$AUTOPAUSE_KNOCK_INTERFACE\"."
46+
autopause_error_loop
2247
fi
2348

2449
STATE=INIT

files/autopause/autopause-fcns.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ java_running() {
88
[[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]]
99
}
1010

11+
java_process_exists() {
12+
[[ -n "$(ps -a -o comm | grep 'java')" ]]
13+
}
14+
1115
rcon_client_exists() {
1216
[[ -n "$(ps -a -o comm | grep 'rcon-cli')" ]]
1317
}

files/autopause/pause.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ if [[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]] ; th
1717

1818
# finally pause the process
1919
logAutopauseAction "Pausing Java process"
20-
killall -q -STOP java
20+
pkill -STOP java
2121
fi

files/autopause/resume.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44

55
if [[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^T.*$ ]] ; then
66
logAutopauseAction "Knocked, resuming Java process"
7-
killall -q -CONT java
7+
pkill -CONT java
88
fi

files/sudoers-mc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
%minecraft ALL=(ALL) NOPASSWD:/usr/bin/killall
1+
%minecraft ALL=(ALL) NOPASSWD:/usr/bin/pkill
22
%minecraft ALL=(ALL) NOPASSWD:/usr/sbin/knockd

start-autopause

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,15 @@ if ! [[ $AUTOPAUSE_TIMEOUT_INIT =~ ^[0-9]+$ ]] ; then
4646
export AUTOPAUSE_TIMEOUT_INIT
4747
log "Warning: AUTOPAUSE_TIMEOUT_INIT is not numeric, set to 600 (seconds)"
4848
fi
49+
if [[ "$AUTOPAUSE_KNOCK_INTERFACE" == "lo" ]] ; then
50+
log "Warning: AUTOPAUSE_KNOCK_INTERFACE is set to the local loopback interface."
51+
log " This is not advisable, as incoming connections are likely not picked up there."
52+
log " Continuing with this setting."
53+
fi
4954

50-
if [[ -n $MAX_TICK_TIME ]] ; then
55+
if [[ -n "$MAX_TICK_TIME" && "$MAX_TICK_TIME" != "-1" ]] ; then
5156
log "Warning: MAX_TICK_TIME is non-default, for autopause to work properly, this check should be disabled (-1 for versions >= 1.8.1)"
52-
else
57+
elif [[ -z "$MAX_TICK_TIME" ]] ; then
5358
if versionLessThan 1.8.1; then
5459
# 10 years
5560
MAX_TICK_TIME=315360000000

0 commit comments

Comments
 (0)