mirror of
https://github.com/itzg/docker-minecraft-server
synced 2024-12-13 13:52:27 +00:00
Autopause functionality (#531)
This commit is contained in:
parent
ede58d9159
commit
71a7afab17
13 changed files with 324 additions and 10 deletions
21
Dockerfile
21
Dockerfile
|
@ -15,15 +15,17 @@ RUN apk add --no-cache -U \
|
||||||
mysql-client \
|
mysql-client \
|
||||||
tzdata \
|
tzdata \
|
||||||
rsync \
|
rsync \
|
||||||
nano
|
nano \
|
||||||
|
sudo \
|
||||||
HEALTHCHECK --start-period=1m CMD mc-monitor status --host localhost --port $SERVER_PORT
|
knock
|
||||||
|
|
||||||
RUN addgroup -g 1000 minecraft \
|
RUN addgroup -g 1000 minecraft \
|
||||||
&& adduser -Ss /bin/false -u 1000 -G minecraft -h /home/minecraft minecraft \
|
&& adduser -Ss /bin/false -u 1000 -G minecraft -h /home/minecraft minecraft \
|
||||||
&& mkdir -m 777 /data \
|
&& mkdir -m 777 /data \
|
||||||
&& chown minecraft:minecraft /data /home/minecraft
|
&& chown minecraft:minecraft /data /home/minecraft
|
||||||
|
|
||||||
|
COPY files/sudoers* /etc/sudoers.d
|
||||||
|
|
||||||
EXPOSE 25565 25575
|
EXPOSE 25565 25575
|
||||||
|
|
||||||
# hook into docker BuildKit --platform support
|
# hook into docker BuildKit --platform support
|
||||||
|
@ -63,14 +65,21 @@ COPY server.properties /tmp/server.properties
|
||||||
COPY log4j2.xml /tmp/log4j2.xml
|
COPY log4j2.xml /tmp/log4j2.xml
|
||||||
WORKDIR /data
|
WORKDIR /data
|
||||||
|
|
||||||
ENTRYPOINT [ "/start" ]
|
|
||||||
|
|
||||||
ENV UID=1000 GID=1000 \
|
ENV UID=1000 GID=1000 \
|
||||||
JVM_XX_OPTS="-XX:+UseG1GC" MEMORY="1G" \
|
JVM_XX_OPTS="-XX:+UseG1GC" MEMORY="1G" \
|
||||||
TYPE=VANILLA VERSION=LATEST FORGEVERSION=RECOMMENDED SPONGEBRANCH=STABLE SPONGEVERSION= FABRICVERSION=LATEST LEVEL=world \
|
TYPE=VANILLA VERSION=LATEST FORGEVERSION=RECOMMENDED SPONGEBRANCH=STABLE SPONGEVERSION= FABRICVERSION=LATEST LEVEL=world \
|
||||||
PVP=true DIFFICULTY=easy ENABLE_RCON=true RCON_PORT=25575 RCON_PASSWORD=minecraft \
|
PVP=true DIFFICULTY=easy ENABLE_RCON=true RCON_PORT=25575 RCON_PASSWORD=minecraft \
|
||||||
LEVEL_TYPE=DEFAULT SERVER_PORT=25565 ONLINE_MODE=TRUE SERVER_NAME="Dedicated Server" \
|
LEVEL_TYPE=DEFAULT SERVER_PORT=25565 ONLINE_MODE=TRUE SERVER_NAME="Dedicated Server" \
|
||||||
REPLACE_ENV_VARIABLES="FALSE" ENV_VARIABLE_PREFIX="CFG_"
|
REPLACE_ENV_VARIABLES="FALSE" ENV_VARIABLE_PREFIX="CFG_" \
|
||||||
|
ENABLE_AUTOPAUSE=false AUTOPAUSE_TIMEOUT_EST=3600 AUTOPAUSE_TIMEOUT_KN=120 AUTOPAUSE_TIMEOUT_INIT=600 AUTOPAUSE_PERIOD=10
|
||||||
|
|
||||||
COPY start* /
|
COPY start* /
|
||||||
|
COPY health.sh /
|
||||||
|
ADD files/autopause /autopause
|
||||||
|
|
||||||
RUN dos2unix /start* && chmod +x /start*
|
RUN dos2unix /start* && chmod +x /start*
|
||||||
|
RUN dos2unix /health.sh && chmod +x /health.sh
|
||||||
|
RUN dos2unix /autopause/* && chmod +x /autopause/*.sh
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/start" ]
|
||||||
|
HEALTHCHECK --start-period=1m CMD /health.sh
|
||||||
|
|
34
README.md
34
README.md
|
@ -179,6 +179,40 @@ You can also query the container's health in a script friendly way:
|
||||||
healthy
|
healthy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Autopause
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
> 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)).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Of course, even loaded chunks are not ticked when the process is stopped.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
The autopause functionality is not compatible with docker's host network_mode, as the `knockd` utility cannot properly listen for connections in that mode.
|
||||||
|
|
||||||
|
### Enabling Autopause
|
||||||
|
|
||||||
|
Enable the Autopause functionality by setting:
|
||||||
|
|
||||||
|
```
|
||||||
|
-e ENABLE_AUTOPAUSE=TRUE
|
||||||
|
```
|
||||||
|
|
||||||
|
There are 4 more environment variables that define the behaviour:
|
||||||
|
* `AUTOPAUSE_TIMEOUT_EST`, default `3600` (seconds)
|
||||||
|
describes the time between the last client disconnect and the pausing of the process (read as timeout established)
|
||||||
|
* `AUTOPAUSE_TIMEOUT_INIT`, default `600` (seconds)
|
||||||
|
describes the time between server start and the pausing of the process, when no client connects inbetween (read as timeout initialized)
|
||||||
|
* `AUTOPAUSE_TIMEOUT_KN`, default `120` (seconds)
|
||||||
|
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)
|
||||||
|
* `AUTOPAUSE_PERIOD`, default `10` (seconds)
|
||||||
|
describes period of the daemonized state machine, that handles the pausing of the process (resuming is done independently)
|
||||||
|
|
||||||
## Deployment Templates and Examples
|
## Deployment Templates and Examples
|
||||||
|
|
||||||
### Helm Charts
|
### Helm Charts
|
||||||
|
|
97
files/autopause/autopause-daemon.sh
Normal file
97
files/autopause/autopause-daemon.sh
Normal 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
files/autopause/autopause-fcns.sh
Normal file
38
files/autopause/autopause-fcns.sh
Normal 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
files/autopause/knockd-config.cfg
Normal file
12
files/autopause/knockd-config.cfg
Normal 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
files/autopause/pause.sh
Executable file
19
files/autopause/pause.sh
Executable 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
files/autopause/resume.sh
Executable file
6
files/autopause/resume.sh
Executable 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
files/sudoers-mc
Normal file
2
files/sudoers-mc
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
%minecraft ALL=(ALL) NOPASSWD:/usr/bin/killall
|
||||||
|
%minecraft ALL=(ALL) NOPASSWD:/usr/sbin/knockd
|
11
health.sh
Normal file
11
health.sh
Normal file
|
@ -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
|
8
start
8
start
|
@ -36,6 +36,14 @@ if [ $(id -u) = 0 ]; then
|
||||||
chown -R ${runAsUser}:${runAsGroup} /data
|
chown -R ${runAsUser}:${runAsGroup} /data
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ $(stat -c "%u" /autopause) != $UID ]]; then
|
||||||
|
log "Changing ownership of /autopause to $UID ..."
|
||||||
|
chown -R ${runAsUser}:${runAsGroup} /autopause
|
||||||
|
fi
|
||||||
|
|
||||||
|
ln -fs $(tty) /tmp/terminal-mc
|
||||||
|
chmod 777 /tmp/terminal-mc
|
||||||
|
|
||||||
if [[ ${SKIP_NSSWITCH_CONF^^} != TRUE ]]; then
|
if [[ ${SKIP_NSSWITCH_CONF^^} != TRUE ]]; then
|
||||||
echo 'hosts: files dns' > /etc/nsswitch.conf
|
echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -68,6 +68,65 @@ cd /data || exit 1
|
||||||
|
|
||||||
export ORIGINAL_TYPE=${TYPE^^}
|
export ORIGINAL_TYPE=${TYPE^^}
|
||||||
|
|
||||||
|
if isTrue "${ENABLE_AUTOPAUSE}"; then
|
||||||
|
log "Autopause functionality enabled"
|
||||||
|
|
||||||
|
# update server port to listen to
|
||||||
|
regseq="^\s*sequence\s*=\s*$SERVER_PORT\s*$"
|
||||||
|
linenum=$(grep -nm1 sequence /autopause/knockd-config.cfg | cut -d : -f 1 | tail -n1)
|
||||||
|
if ! [[ $(awk "NR==$linenum" /autopause/knockd-config.cfg) =~ $regseq ]]; then
|
||||||
|
sed -i "${linenum}s/sequence.*/sequence = $SERVER_PORT/" /autopause/knockd-config.cfg
|
||||||
|
log "Updated server port in knockd config"
|
||||||
|
fi
|
||||||
|
# update rcon port to listen to
|
||||||
|
regseq="^\s*sequence\s*=\s*$RCON_PORT\s*$"
|
||||||
|
linenum=$(grep -nm2 sequence /autopause/knockd-config.cfg | cut -d : -f 1 | tail -n1)
|
||||||
|
if ! [[ $(awk "NR==$linenum" /autopause/knockd-config.cfg) =~ $regseq ]]; then
|
||||||
|
sed -i "${linenum}s/sequence.*/sequence = $RCON_PORT/" /autopause/knockd-config.cfg
|
||||||
|
log "Updated rcon port in knockd config"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ $AUTOPAUSE_PERIOD =~ ^[0-9]+$ ]]; then
|
||||||
|
AUTOPAUSE_PERIOD=10
|
||||||
|
export AUTOPAUSE_PERIOD
|
||||||
|
log "Warning: AUTOPAUSE_PERIOD is not numeric, set to 10 (seconds)"
|
||||||
|
fi
|
||||||
|
if [ "$AUTOPAUSE_PERIOD" -eq "0" ] ; then
|
||||||
|
AUTOPAUSE_PERIOD=10
|
||||||
|
export AUTOPAUSE_PERIOD
|
||||||
|
log "Warning: AUTOPAUSE_PERIOD must not be 0, set to 10 (seconds)"
|
||||||
|
fi
|
||||||
|
if ! [[ $AUTOPAUSE_TIMEOUT_KN =~ ^[0-9]+$ ]] ; then
|
||||||
|
AUTOPAUSE_TIMEOUT_KN=120
|
||||||
|
export AUTOPAUSE_TIMEOUT_KN
|
||||||
|
log "Warning: AUTOPAUSE_TIMEOUT_KN is not numeric, set to 120 (seconds)"
|
||||||
|
fi
|
||||||
|
if ! [[ $AUTOPAUSE_TIMEOUT_EST =~ ^[0-9]+$ ]] ; then
|
||||||
|
AUTOPAUSE_TIMEOUT_EST=3600
|
||||||
|
export AUTOPAUSE_TIMEOUT_EST
|
||||||
|
log "Warning: AUTOPAUSE_TIMEOUT_EST is not numeric, set to 3600 (seconds)"
|
||||||
|
fi
|
||||||
|
if ! [[ $AUTOPAUSE_TIMEOUT_INIT =~ ^[0-9]+$ ]] ; then
|
||||||
|
AUTOPAUSE_TIMEOUT_INIT=600
|
||||||
|
export AUTOPAUSE_TIMEOUT_INIT
|
||||||
|
log "Warning: AUTOPAUSE_TIMEOUT_INIT is not numeric, set to 600 (seconds)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n $MAX_TICK_TIME ]] ; then
|
||||||
|
log "Warning: MAX_TICK_TIME is non-default, for autopause to work properly, this check should be disabled (-1 for versions >= 1.8.1)"
|
||||||
|
else
|
||||||
|
if versionLessThan 1.8.1; then
|
||||||
|
# 10 years
|
||||||
|
MAX_TICK_TIME=315360000000
|
||||||
|
else
|
||||||
|
MAX_TICK_TIME=-1
|
||||||
|
fi
|
||||||
|
export MAX_TICK_TIME
|
||||||
|
fi
|
||||||
|
|
||||||
|
/autopause/autopause-daemon.sh &
|
||||||
|
fi
|
||||||
|
|
||||||
log "Resolving type given ${TYPE}"
|
log "Resolving type given ${TYPE}"
|
||||||
case "${TYPE^^}" in
|
case "${TYPE^^}" in
|
||||||
*BUKKIT|SPIGOT)
|
*BUKKIT|SPIGOT)
|
||||||
|
|
|
@ -180,4 +180,13 @@ else
|
||||||
log "server.properties already created, skipping"
|
log "server.properties already created, skipping"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if isTrue "${ENABLE_AUTOPAUSE}"; then
|
||||||
|
current_max_tick=$( grep 'max-tick-time' "$SERVER_PROPERTIES" | sed -r 's/( )+//g' | awk -F= '{print $2}' )
|
||||||
|
if (( $current_max_tick > 0 && $current_max_tick < 86400000 )); then
|
||||||
|
log "Warning: The server.properties for the server doesn't have the Server Watchdog (effectively) disabled."
|
||||||
|
log "Warning (cont): Autopause functionality resuming the process might trigger the Watchdog and restart the server completely."
|
||||||
|
log "Warning (cont): Set the max-tick-time property to a high value (or disable the Watchdog with value -1 for versions 1.8.1+)."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
exec /start-finalSetup05EnvVariables $@
|
exec /start-finalSetup05EnvVariables $@
|
||||||
|
|
10
start-utils
10
start-utils
|
@ -75,10 +75,20 @@ function versionLessThan {
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if (( ${#activeParts[@]} == 2 )); then
|
||||||
if (( activeParts[0] < givenParts[0] )) || \
|
if (( activeParts[0] < givenParts[0] )) || \
|
||||||
(( activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1] )); then
|
(( activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1] )); then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
if (( activeParts[0] < givenParts[0] )) || \
|
||||||
|
(( activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1] )) || \
|
||||||
|
(( activeParts[0] == givenParts[0] && activeParts[1] == givenParts[1] && activeParts[2] < givenParts[2] )); then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
}
|
}
|
Loading…
Reference in a new issue