From fa4a0e92cee6325d2a4865da5945288f2f82f1ef Mon Sep 17 00:00:00 2001 From: Michael Kirsch Date: Tue, 21 Dec 2021 01:27:27 +0100 Subject: [PATCH] Autostop feature (#1212) --- Dockerfile | 6 ++- README.md | 22 +++++++++ examples/docker-compose-autostop.yml | 20 ++++++++ files/autostop/autostop-daemon.sh | 69 ++++++++++++++++++++++++++++ files/autostop/stop.sh | 6 +++ scripts/start-autostop | 34 ++++++++++++++ scripts/start-configuration | 9 ++++ scripts/start-utils | 8 ++++ 8 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 examples/docker-compose-autostop.yml create mode 100755 files/autostop/autostop-daemon.sh create mode 100755 files/autostop/stop.sh create mode 100755 scripts/start-autostop diff --git a/Dockerfile b/Dockerfile index 1be78a00..7beb2c13 100644 --- a/Dockerfile +++ b/Dockerfile @@ -76,7 +76,8 @@ ENV UID=1000 GID=1000 \ TYPE=VANILLA VERSION=LATEST \ ENABLE_RCON=true RCON_PORT=25575 RCON_PASSWORD=minecraft \ ENABLE_AUTOPAUSE=false AUTOPAUSE_TIMEOUT_EST=3600 AUTOPAUSE_TIMEOUT_KN=120 AUTOPAUSE_TIMEOUT_INIT=600 \ - AUTOPAUSE_PERIOD=10 AUTOPAUSE_KNOCK_INTERFACE=eth0 + AUTOPAUSE_PERIOD=10 AUTOPAUSE_KNOCK_INTERFACE=eth0 \ + ENABLE_AUTOSTOP=false AUTOSTOP_TIMEOUT_EST=3600 AUTOSTOP_TIMEOUT_INIT=1800 AUTOSTOP_PERIOD=10 COPY --chmod=755 scripts/start* / COPY --chmod=755 bin/ /usr/local/bin/ @@ -84,8 +85,9 @@ COPY --chmod=755 bin/mc-health /health.sh COPY --chmod=644 files/server.properties /tmp/server.properties COPY --chmod=644 files/log4j2.xml /tmp/log4j2.xml COPY --chmod=755 files/autopause /autopause +COPY --chmod=755 files/autostop /autostop -RUN dos2unix /start* /autopause/* +RUN dos2unix /start* /autopause/* /autostop/* ENTRYPOINT [ "/start" ] HEALTHCHECK --start-period=1m CMD mc-health diff --git a/README.md b/README.md index ad18af7f..48a6dd4a 100644 --- a/README.md +++ b/README.md @@ -1459,6 +1459,28 @@ The following environment variables define the behaviour of auto-pausing: * `AUTOPAUSE_KNOCK_INTERFACE`, default `eth0`
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. +## Autostop + +An option to stop the server after a specified time has been added for niche applications (e.g. billing saving on AWS Fargate). The function is incompatible with the Autopause functionality, as they basically cancel out each other. + +Note that the docker container variables have to be set accordingly (restart policy set to "no") and that the container has to be manually restarted. + +A starting, example compose file has been provided in [examples/docker-compose-autostop.yml](examples/docker-compose-autostop.yml). + +Enable the Autostop functionality by setting: + +``` +-e ENABLE_AUTOSTOP=TRUE +``` + +The following environment variables define the behaviour of auto-stopping: +* `AUTOSTOP_TIMEOUT_EST`, default `3600` (seconds) + describes the time between the last client disconnect and the stopping of the server (read as timeout established) +* `AUTOSTOP_TIMEOUT_INIT`, default `1800` (seconds) + describes the time between server start and the stopping of the server, when no client connects inbetween (read as timeout initialized) +* `AUTOSTOP_PERIOD`, default `10` (seconds) + describes period of the daemonized state machine, that handles the stopping of the server + ## Running on RaspberryPi To run this image on a RaspberryPi 3 B+, 4, or newer, use any of the image tags [list in the Java version section](#running-minecraft-server-on-different-java-version) that specify `armv7` for the architecture, which includes `itzg/minecraft-server:latest`. diff --git a/examples/docker-compose-autostop.yml b/examples/docker-compose-autostop.yml new file mode 100644 index 00000000..5d45421a --- /dev/null +++ b/examples/docker-compose-autostop.yml @@ -0,0 +1,20 @@ +version: '3.8' + +services: + minecraft: + image: itzg/minecraft-server + ports: + - "25565:25565" + volumes: + - "mc:/data" + environment: + EULA: "TRUE" + ENABLE_AUTOSTOP: "TRUE" + # More aggressive settings for demo purposes + AUTOSTOP_TIMEOUT_INIT: "30" + AUTOSTOP_TIMEOUT_EST: "20" + # Important not to auto-restart the server!!! + restart: "no" + +volumes: + mc: {} diff --git a/files/autostop/autostop-daemon.sh b/files/autostop/autostop-daemon.sh new file mode 100755 index 00000000..0d6aa2ad --- /dev/null +++ b/files/autostop/autostop-daemon.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +# needed for the clients connected function residing in autopause +. /autopause/autopause-fcns.sh + +. ${SCRIPTS:-/}start-utils + +# wait for java process to be started +while : +do + if java_process_exists ; then + break + fi + sleep 0.1 +done + +STATE=INIT + +while : +do + case X$STATE in + XINIT) + # Server startup + if mc_server_listening ; then + TIME_THRESH=$(($(current_uptime)+$AUTOSTOP_TIMEOUT_INIT)) + logAutostop "MC Server listening for connections - stopping in $AUTOSTOP_TIMEOUT_INIT seconds" + STATE=II + fi + ;; + XII) + # Initial idle + if java_clients_connected ; then + logAutostop "Client connected - waiting for disconnect" + STATE=E + else + if [[ $(current_uptime) -ge $TIME_THRESH ]] ; then + logAutostop "No client connected since startup - stopping server" + /autostop/stop.sh + exit 0 + fi + fi + ;; + XE) + # Established + if ! java_clients_connected ; then + TIME_THRESH=$(($(current_uptime)+$AUTOSTOP_TIMEOUT_EST)) + logAutostop "All clients disconnected - stopping in $AUTOSTOP_TIMEOUT_EST seconds" + STATE=I + fi + ;; + XI) + # Idle + if java_clients_connected ; then + logAutostop "Client reconnected - waiting for disconnect" + STATE=E + else + if [[ $(current_uptime) -ge $TIME_THRESH ]] ; then + logAutostop "No client reconnected - stopping" + /autostop/stop.sh + exit 0 + fi + fi + ;; + *) + logAutostop "Error: invalid state: $STATE" + ;; + esac + sleep $AUTOSTOP_PERIOD +done diff --git a/files/autostop/stop.sh b/files/autostop/stop.sh new file mode 100755 index 00000000..1a9ed2f4 --- /dev/null +++ b/files/autostop/stop.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +. /start-utils + +logAutostopAction "Stopping Java process" +kill -SIGTERM 1 diff --git a/scripts/start-autostop b/scripts/start-autostop new file mode 100755 index 00000000..b71bf395 --- /dev/null +++ b/scripts/start-autostop @@ -0,0 +1,34 @@ +#!/bin/bash + +# shellcheck source=start-utils +. "${SCRIPTS:-/}start-utils" + +: "${SERVER_PORT:=25565}" +export SERVER_PORT + +log "Autostop functionality enabled" + +isDebugging && set -x + +if ! [[ $AUTOSTOP_PERIOD =~ ^[0-9]+$ ]]; then + AUTOSTOP_PERIOD=10 + export AUTOSTOP_PERIOD + log "Warning: AUTOSTOP_PERIOD is not numeric, set to 10 (seconds)" +fi +if [ "$AUTOSTOP_PERIOD" -eq "0" ] ; then + AUTOSTOP_PERIOD=10 + export AUTOSTOP_PERIOD + log "Warning: AUTOSTOP_PERIOD must not be 0, set to 10 (seconds)" +fi +if ! [[ $AUTOSTOP_TIMEOUT_EST =~ ^[0-9]+$ ]] ; then + AUTOSTOP_TIMEOUT_EST=3600 + export AUTOSTOP_TIMEOUT_EST + log "Warning: AUTOSTOP_TIMEOUT_EST is not numeric, set to 3600 (seconds)" +fi +if ! [[ $AUTOSTOP_TIMEOUT_INIT =~ ^[0-9]+$ ]] ; then + AUTOSTOP_TIMEOUT_INIT=1800 + export AUTOSTOP_TIMEOUT_INIT + log "Warning: AUTOSTOP_TIMEOUT_INIT is not numeric, set to 1800 (seconds)" +fi + +/autostop/autostop-daemon.sh & diff --git a/scripts/start-configuration b/scripts/start-configuration index f1eed964..cfeb0fcb 100755 --- a/scripts/start-configuration +++ b/scripts/start-configuration @@ -37,6 +37,11 @@ if isTrue "${ENABLE_AUTOPAUSE}" && isTrue "${EXEC_DIRECTLY:-false}"; then exit 1 fi +if isTrue "${ENABLE_AUTOPAUSE}" && isTrue "${ENABLE_AUTOSTOP}"; then + log "ENABLE_AUTOPAUSE=true is incompatible with ENABLE_AUTOSTOP=true" + exit 1 +fi + if [[ $PROXY ]]; then export http_proxy="$PROXY" export https_proxy="$PROXY" @@ -96,6 +101,10 @@ if isTrue "${ENABLE_AUTOPAUSE}"; then ${SCRIPTS:-/}start-autopause fi +if isTrue "${ENABLE_AUTOSTOP}"; then + ${SCRIPTS:-/}start-autostop +fi + if versionLessThan 1.7; then echo " MC_HEALTH_EXTRA_ARGS=( diff --git a/scripts/start-utils b/scripts/start-utils index 1a2ed977..8c77cbca 100755 --- a/scripts/start-utils +++ b/scripts/start-utils @@ -93,6 +93,14 @@ function logAutopauseAction() { echo "[$(date -Iseconds)] [Autopause] $*" } +function logAutostop() { + echo "[Autostop loop] $*" +} + +function logAutostopAction() { + echo "[$(date -Iseconds)] [Autostop] $*" +} + function normalizeMemSize() { local scale=1 case ${1,,} in