summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorBuildTools2016-04-27 15:49:37 -0700
committerBuildTools2016-04-27 15:49:37 -0700
commitf52bcd11078cf46c294dc14965694f29134bd79d (patch)
treefa07394842b28ac1be83cfa8b5516ff3c9d261c1
parenta567faf23b731bb2736d8754e8ff42709983a096 (diff)
downloadaur-f52bcd11078cf46c294dc14965694f29134bd79d.tar.gz
New config / run script updates from edh
-rw-r--r--.SRCINFO19
-rwxr-xr-xPKGBUILD60
-rw-r--r--spigot-backup.service2
-rw-r--r--spigot.conf19
-rwxr-xr-xspigot.install66
-rwxr-xr-xspigot.service4
-rwxr-xr-xspigot.sh324
7 files changed, 346 insertions, 148 deletions
diff --git a/.SRCINFO b/.SRCINFO
index d151f081119..f3789d8c0a3 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,10 +1,10 @@
# Generated by mksrcinfo v8
-# Fri Apr 1 06:44:57 UTC 2016
+# Wed Apr 27 22:47:30 UTC 2016
pkgbase = spigot
pkgdesc = High performance Minecraft server implementation
pkgver = 1.9.2
- pkgrel = 1
- url = http://www.spigotmc.org/
+ pkgrel = 2
+ url = https://www.spigotmc.org/
install = spigot.install
arch = any
license = LGPL
@@ -16,9 +16,10 @@ pkgbase = spigot
depends = fontconfig
depends = bash
optdepends = tar: needed in order to create world backups
- provides = bukkit
- provides = craftbukkit=1.9.2
+ optdepends = netcat: required in order to suspend an idle server
provides = minecraft-server=1.9.2
+ provides = bukkit=1.9.2
+ provides = craftbukkit=1.9.2
conflicts = bukkit
conflicts = craftbukkit
conflicts = spigot-patcher
@@ -31,11 +32,11 @@ pkgbase = spigot
source = spigot.conf
source = spigot.sh
md5sums = SKIP
- md5sums = fd17202ba0bb7796439f0b2f6bc53be4
+ md5sums = 7bb2dc610c5f55e133bd41ab608ec7a1
md5sums = 872d2e03799f1f8f0c75acdebce91894
- md5sums = 580c470c92d88ae2362250d59bd33b10
- md5sums = 675f4b1080f2543f43058c7124dcafc2
- md5sums = 0f79c1689c5fc4dbd5408a1a37118950
+ md5sums = 1eb2d5f485cf9eff7a99c826ad56fcf4
+ md5sums = f04e0bcf8d771b0d1dc0206dc173d77a
+ md5sums = 6ee73f849e2caf6d8c89c73a80cc0c33
pkgname = spigot
diff --git a/PKGBUILD b/PKGBUILD
index 18f0425bc5b..684af128466 100755
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,43 +1,55 @@
# Maintainer: Gordian Edenhofer <gordian.edenhofer[at]yahoo[dot]de>
+
pkgname=spigot
pkgver=1.9.2
-pkgrel=1
+pkgrel=2
pkgdesc="High performance Minecraft server implementation"
arch=(any)
-url="http://www.spigotmc.org/"
+url="https://www.spigotmc.org/"
license=("LGPL")
depends=(java-runtime-headless screen sudo fontconfig bash)
+optdepends=("tar: needed in order to create world backups"
+"netcat: required in order to suspend an idle server")
makedepends=(java-environment git)
-optdepends=("tar: needed in order to create world backups")
+provides=("minecraft-server=${pkgver%_*}" "bukkit=${pkgver%_*}" "craftbukkit=${pkgver%_*}")
conflicts=(bukkit craftbukkit spigot-patcher)
-provides=(bukkit "craftbukkit=${pkgver%_*}" "minecraft-server=${pkgver%_*}")
-install=${pkgname}.install
+backup=("etc/conf.d/${pkgname}")
+install="${pkgname}.install"
source=("https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar"
- "${pkgname}-backup.service"
- "${pkgname}-backup.timer"
- "${pkgname}.service"
- "${pkgname}.conf"
- "${pkgname}.sh")
+"${pkgname}-backup.service"
+"${pkgname}-backup.timer"
+"${pkgname}.service"
+"${pkgname}.conf"
+"${pkgname}.sh")
noextract=("BuildTools.jar")
md5sums=('SKIP'
- 'fd17202ba0bb7796439f0b2f6bc53be4'
+ '7bb2dc610c5f55e133bd41ab608ec7a1'
'872d2e03799f1f8f0c75acdebce91894'
- '580c470c92d88ae2362250d59bd33b10'
- '675f4b1080f2543f43058c7124dcafc2'
- '0f79c1689c5fc4dbd5408a1a37118950')
-backup=("etc/conf.d/${pkgname}")
+ '1eb2d5f485cf9eff7a99c826ad56fcf4'
+ 'f04e0bcf8d771b0d1dc0206dc173d77a'
+ '6ee73f849e2caf6d8c89c73a80cc0c33')
+
+_game="spigot"
+_server_root="/srv/craftbukkit"
build() {
export MAVEN_OPTS="-Xmx2g -XX:MaxPermSize=1g"
- java -jar BuildTools.jar --rev $pkgver
+ java -jar BuildTools.jar --rev ${pkgver}
}
+
package() {
- install -Dm644 ${pkgname}.conf "${pkgdir}/etc/conf.d/${pkgname}"
- install -Dm755 ${pkgname}.sh "${pkgdir}/usr/bin/${pkgname}"
- install -Dm644 ${pkgname}-${pkgver}.jar "${pkgdir}/srv/craftbukkit/${pkgname}.jar"
- install -Dm644 ${pkgname}.service "${pkgdir}/usr/lib/systemd/system/${pkgname}.service"
- install -Dm644 ${pkgname}-backup.service "${pkgdir}/usr/lib/systemd/system/${pkgname}-backup.service"
- install -Dm644 ${pkgname}-backup.timer "${pkgdir}/usr/lib/systemd/system/${pkgname}-backup.timer"
-}
+ install -Dm644 ${_game}.conf "${pkgdir}/etc/conf.d/${_game}"
+ install -Dm755 ${_game}.sh "${pkgdir}/usr/bin/${_game}"
+ install -Dm644 ${_game}.service "${pkgdir}/usr/lib/systemd/system/${_game}.service"
+ install -Dm644 ${_game}-backup.service "${pkgdir}/usr/lib/systemd/system/${_game}-backup.service"
+ install -Dm644 ${_game}-backup.timer "${pkgdir}/usr/lib/systemd/system/${_game}-backup.timer"
+ install -Dm644 ${_game}-${pkgver}.jar "${pkgdir}${_server_root}/${_game}.${pkgver}.jar"
+ ln -s "${_game}.${pkgver}.jar" "${pkgdir}${_server_root}/${_game}.jar"
-# vim:set ts=2 sw=2 et:
+ # Link the log files
+ mkdir -p "${pkgdir}/var/log/"
+ ln -s "${_server_root}/logs" "${pkgdir}/var/log/${_game}"
+
+ # Give the group write permissions and set user or group ID on execution
+ chmod g+ws "${pkgdir}${_server_root}"
+}
diff --git a/spigot-backup.service b/spigot-backup.service
index 4eda131909d..9d64e48bf5c 100644
--- a/spigot-backup.service
+++ b/spigot-backup.service
@@ -5,6 +5,8 @@ After=local-fs.target
[Service]
Type=forking
ExecStart=/usr/bin/spigot backup
+User=craftbukkit
+Group=craftbukkit
[Install]
WantedBy=multi-user.target
diff --git a/spigot.conf b/spigot.conf
index 7d2fe630371..ebe90d70c61 100644
--- a/spigot.conf
+++ b/spigot.conf
@@ -3,16 +3,25 @@
# General parameters
SERVER_ROOT="/srv/craftbukkit"
-BACKUPPATH="/srv/craftbukkit/backup"
+BACKUP_DEST="/srv/craftbukkit/backup"
LOGPATH="/srv/craftbukkit/logs"
-WORLDPATHS="world world_nether world_the_end" # World paths separated by spaces relative to SERVER_ROOT
+BACKUP_PATHS="world world_nether world_the_end" # World paths separated by spaces relative to SERVER_ROOT
KEEP_BACKUPS="10"
-MC_USER="craftbukkit"
-MAIN_JAR="spigot.jar"
+GAME_USER="craftbukkit"
+MAIN_EXECUTABLE="spigot.jar"
SESSION_NAME="spigot"
-# System parameters for the minecraft server
+# System parameters for java
MINHEAP="512M"
MAXHEAP="1024M"
THREADS="1"
JAVA_PARMS="-Xmx${MAXHEAP} -Xms${MINHEAP} -XX:ParallelGCThreads=${THREADS}"
+
+# System parameters for the actual game server
+# Describes whether a daemon process which stops the server if it is not used by a player
+# within IDLE_IF_TIME seconds should be started. The GAME_PORT is not inhereted to the server!
+IDLE_SERVER=false # true or false
+IDLE_SESSION_NAME="idle_server"
+GAME_PORT="25565" # used to listen for incoming connections when the server is down
+CHECK_PLAYER_TIME="30" # in seconds
+IDLE_IF_TIME="1200" # in seconds
diff --git a/spigot.install b/spigot.install
index 9422066f97b..27d960b031b 100755
--- a/spigot.install
+++ b/spigot.install
@@ -1,58 +1,64 @@
-USER="craftbukkit"
-SERVER_ROOT="/srv/craftbukkit"
+_game="spigot"
+_user="craftbukkit"
+_server_root="/srv/craftbukkit"
post_install() {
- getent group "${USER}" &>/dev/null
+ getent group "${_user}" &>/dev/null
if [ $? -ne 0 ]; then
- echo -e "\e[34;1m==>\e[39;1m Adding ${USER} system group... \e[0m"
- groupadd -r ${USER} 1>/dev/null
+ echo -e "\e[34;1m==>\e[39;1m Adding ${_user} system group... \e[0m"
+ groupadd -r ${_user} 1>/dev/null
fi
- getent passwd "${USER}" &>/dev/null
+ getent passwd "${_user}" &>/dev/null
if [ $? -ne 0 ]; then
- echo -e "\e[34;1m==>\e[39;1m Adding ${USER} system user... \e[0m"
- useradd -r -g ${USER} -d "${SERVER_ROOT}" ${USER} 1>/dev/null
+ echo -e "\e[34;1m==>\e[39;1m Adding ${_user} system user... \e[0m"
+ useradd -r -g ${_user} -d "${_server_root}" ${_user} 1>/dev/null
fi
- chown -R ${USER}:${USER} "${SERVER_ROOT}"
+ chown -R ${_user}:${_user} "${_server_root}"
- echo -e "\e[34;1m==>\e[39;1m NOTE: The world data is stored under ${SERVER_ROOT} and the server runs \e[0m"
- echo -e "\e[34;1m==>\e[39;1m as ${USER} user to increase security. \e[0m"
- echo -e "\e[34;1m==>\e[39;1m NOTE: Use the spigot script under /usr/bin/spigot to start, stop or backup the server \e[0m"
- echo -e "\e[34;1m==>\e[39;1m and the configuration file under /etc/conf.d/spigot to adjust it to your liking. \e[0m"
- echo -e "\e[34;1m==>\e[39;1m NOTE: For the server to start you have to accept the EULA in ${SERVER_ROOT}/eula.txt \e[0m"
+ echo -e "\e[34;1m==>\e[39;1m NOTE: The world data is stored under ${_server_root} and the server runs \e[0m"
+ echo -e "\e[34;1m==>\e[39;1m as ${_user} user to increase security. \e[0m"
+ echo -e "\e[34;1m==>\e[39;1m NOTE: Use the ${_game} script under /usr/bin/${_game} to start, stop or backup the server \e[0m"
+ echo -e "\e[34;1m==>\e[39;1m and the configuration file under /etc/conf.d/${_game} to adjust it to your liking. \e[0m"
+ echo -e "\e[34;1m==>\e[39;1m NOTE: For the server to start you have to accept the EULA in ${_server_root}/eula.txt \e[0m"
echo -e "\e[34;1m==>\e[39;1m which is generated after the first server start. \e[0m"
}
post_upgrade() {
- chown -R ${USER}:${USER} "${SERVER_ROOT}"
+ chown -R ${_user}:${_user} "${_server_root}"
- if [[ -f /etc/conf.d/minecraft.pacnew ]]; then
+ if [[ -f /etc/conf.d/${_game}.pacnew ]]; then # TODO: remove oneday
echo -e "\e[34;1m==>\e[39;1m NOTE: There was a new change on how backup files are handled! Unfortunately this makes \e[0m"
echo -e "\e[34;1m==>\e[39;1m old backups incompatible with the newly implemeted restore feature. Bare in mind that no data is lost \e[0m"
echo -e "\e[34;1m==>\e[39;1m neither are those backups useless. They just will not work with the restore capability of the management script. \e[0m"
- echo -e "\e[34;1m==>\e[39;1m NOTE: Please merge the new configuration file into /etc/conf.d/minecraft by e.g. using pacdiff. \e[0m"
+ echo -e "\e[34;1m==>\e[39;1m NOTE: Please merge the new configuration file into /etc/conf.d/${_game} by e.g. using pacdiff. \e[0m"
+ fi
+
+ if [[ -d /srv/spigot ]]; then # TODO: remove oneday
+ echo -e "\e[34;1m==>\e[39;1m NOTE: The server root in the config files and script was moved to /srv/craftbukkit in order to restore compatibility \e[0m"
+ echo -e "\e[34;1m==>\e[39;1m with craftbukkit plugins. Please move your exisiting game save, plugins, backups, logs etc. to this new loaction. \e[0m"
fi
}
pre_remove() {
- echo -e "\e[34;1m==>\e[39;1m Stopping and disabling spigot daemon... \e[0m"
- systemctl stop spigot.service
- systemctl disable spigot.service
+ echo -e "\e[34;1m==>\e[39;1m Stopping and disabling ${_game}... \e[0m"
+ systemctl stop ${_game}.service
+ systemctl disable ${_game}.service
- /usr/bin/spigot stop > /dev/null
+ /usr/bin/${_game} stop > /dev/null
}
post_remove() {
- echo -e "\e[34;1m==>\e[39;1m Removing ${USER} system user and group... \e[0m"
- if getent passwd ${USER} >/dev/null 2>&1; then
- userdel ${USER} 2>/dev/null
+ # Notifying the user of kept dirs
+ [[ -d "${_server_root}" ]] && chown -R root:root "${_server_root}" && echo -e "\e[34;1m==>\e[39;1m NOTE: Game saves in ${_server_root} were kept on your system.\e[0m"
+ [[ -f "/etc/conf.d/${_game}" ]] && echo -e "\e[34;1m==>\e[39;1m NOTE: Your configuration file /etc/conf.d/${_game} was kept on your system.\e[0m"
+
+ echo -e "\e[34;1m==>\e[39;1m Removing ${_user} system user and group... \e[0m"
+ if getent passwd ${_user} >/dev/null 2>&1; then
+ userdel ${_user} 2>/dev/null
fi
- if getent group ${USER} >/dev/null 2>&1; then
- groupdel ${USER}
+ if getent group ${_user} >/dev/null 2>&1; then
+ groupdel ${_user}
fi
-
- # Notifying the user of kept dirs
- [[ -d "${SERVER_ROOT}" ]] && chown -R root:root "${SERVER_ROOT}" && echo -e "\e[34;1m==>\e[39;1m NOTE: Game saves in ${SERVER_ROOT} were kept on your system.\e[0m"
- [[ -f "/etc/conf.d/spigot" ]] && echo -e "\e[34;1m==>\e[39;1m NOTE: Your configuration file /etc/conf.d/spigot was kept on your system.\e[0m"
}
diff --git a/spigot.service b/spigot.service
index 7178066f2f6..99406f0b215 100755
--- a/spigot.service
+++ b/spigot.service
@@ -3,9 +3,11 @@ Description=Spigot
After=local-fs.target network.target
[Service]
+Type=forking
ExecStart=/usr/bin/spigot start
ExecStop=/usr/bin/spigot stop
-Type=forking
+User=craftbukkit
+Group=craftbukkit
[Install]
WantedBy=multi-user.target
diff --git a/spigot.sh b/spigot.sh
index 697eb9ecfcf..dc4f0ed8832 100755
--- a/spigot.sh
+++ b/spigot.sh
@@ -1,73 +1,218 @@
#!/bin/bash
-source /etc/conf.d/spigot || echo "Could not source /etc/conf.d/spigot"
+# The actual program name
+declare -r myname="spigot"
+declare -r game="spigot"
-# General rule variable naming schema:
+# General rule for the variable-naming-schema:
# Variables in capital letters may be passed through the command line others not.
+# Avoid altering any of those later in the code since they may be readonly (IDLE_SERVER is an exception!)
+
+# You may use this script for any game server of your choice, just alter the config file
+[[ ! -z "${SERVER_ROOT}" ]] && declare -r SERVER_ROOT=${SERVER_ROOT} || SERVER_ROOT="/srv/craftbukkit"
+[[ ! -z "${BACKUP_DEST}" ]] && declare -r BACKUP_DEST=${BACKUP_DEST} || BACKUP_DEST="/srv/craftbukkit/backup"
+[[ ! -z "${LOGPATH}" ]] && declare -r LOGPATH=${LOGPATH} || LOGPATH="/srv/craftbukkit/logs"
+[[ ! -z "${BACKUP_PATHS}" ]] && declare -r BACKUP_PATHS=${BACKUP_PATHS} || BACKUP_PATHS="world world_nether world_the_end"
+[[ ! -z "${KEEP_BACKUPS}" ]] && declare -r KEEP_BACKUPS=${KEEP_BACKUPS} || KEEP_BACKUPS="10"
+[[ ! -z "${GAME_USER}" ]] && declare -r GAME_USER=${GAME_USER} || GAME_USER="craftbukkit"
+[[ ! -z "${MAIN_EXECUTABLE}" ]] && declare -r MAIN_EXECUTABLE=${MAIN_EXECUTABLE} || MAIN_EXECUTABLE="spigot.jar"
+[[ ! -z "${SESSION_NAME}" ]] && declare -r SESSION_NAME=${SESSION_NAME} || SESSION_NAME="${game}"
+
+# System parameters for java
+[[ ! -z "${MINHEAP}" ]] && declare -r MINHEAP=${MINHEAP} || MINHEAP="512M"
+[[ ! -z "${MAXHEAP}" ]] && declare -r MAXHEAP=${MAXHEAP} || MAXHEAP="1024M"
+[[ ! -z "${THREADS}" ]] && declare -r THREADS=${THREADS} || THREADS="1"
+[[ ! -z "${JAVA_PARMS}" ]] && declare -r JAVA_PARMS=${JAVA_PARMS} || JAVA_PARMS="-Xmx${MAXHEAP} -Xms${MINHEAP} -XX:ParallelGCThreads=${THREADS}"
+
+# System parameters for the control script
+[[ ! -z "${IDLE_SERVER}" ]] && tmp_IDLE_SERVER=${IDLE_SERVER} || IDLE_SERVER="false"
+[[ ! -z "${IDLE_SESSION_NAME}" ]] && declare -r IDLE_SESSION_NAME=${IDLE_SESSION_NAME} || IDLE_SESSION_NAME="idle_server"
+[[ ! -z "${GAME_PORT}" ]] && declare -r GAME_PORT=${GAME_PORT} || GAME_PORT="25565"
+[[ ! -z "${CHECK_PLAYER_TIME}" ]] && declare -r CHECK_PLAYER_TIME=${CHECK_PLAYER_TIME} || CHECK_PLAYER_TIME="30"
+[[ ! -z "${IDLE_IF_TIME}" ]] && declare -r IDLE_IF_TIME=${IDLE_IF_TIME} || IDLE_IF_TIME="1200"
+
+# Variables passed over the command line will always override the one from a config file
+source /etc/conf.d/${game} || echo "Could not source /etc/conf.d/${game}"
+
+# Preserve the content of IDLE_SERVER without making it readonly
+[[ ! -z ${tmp_IDLE_SERVER} ]] && IDLE_SERVER=${tmp_IDLE_SERVER}
-# You may use this script for any minecraft server of your choice, just alter the config file
-SERVER_ROOT="${SERVER_ROOT:-/srv/craftbukkit}"
-BACKUPPATH="${BACKUPPATH:-/srv/craftbukkit/backup}"
-LOGPATH="${LOGPATH:-/srv/craftbukkit/logs}"
-WORLDPATHS="${WORLDPATHS:-world world_nether world_the_end}"
-KEEP_BACKUPS="${KEEP_BACKUPS:-10}"
-MC_USER="${MC_USER:-craftbukkit}"
-MAIN_JAR="${MAIN_JAR:-spigot.jar}"
-SESSION_NAME="${SESSION_NAME:-spigot}"
-
-# Specify system parameters for the minecraft server
-MINHEAP="${MINHEAP:-512M}"
-MAXHEAP="${MAXHEAP:-1024M}"
-THREADS="${THREADS:-1}"
-JAVA_PARMS="${JAVA_PARMS:-"-Xmx${MAXHEAP} -Xms${MINHEAP} -XX:ParallelGCThreads=${THREADS}"}"
-
-# The actual program name
-declare -r myname="spigot"
# Check whether sudo is needed at all
-if [[ $(whoami) == ${MC_USER} ]]; then
+if [[ $(whoami) == ${GAME_USER} ]]; then
SUDO_CMD=""
else
- SUDO_CMD="sudo -u ${MC_USER}"
+ SUDO_CMD="sudo -u ${GAME_USER}"
+fi
+
+# Choose which flavor of netcat is to be used
+if which netcat &> /dev/null; then
+ NETCAT_CMD="netcat"
+elif which ncat &> /dev/null; then
+ NETCAT_CMD="ncat"
+else
+ NETCAT_CMD=""
fi
# Check for sudo rigths
-if [[ $(${SUDO_CMD} whoami) != ${MC_USER} ]]; then
- echo -e "You have \e[39;1mno permission\e[0m to run commands as $MC_USER user."
- exit 1
+if [[ $(${SUDO_CMD} whoami) != ${GAME_USER} ]]; then
+ >&2 echo -e "You have \e[39;1mno permission\e[0m to run commands as $GAME_USER user."
+ exit 21
fi
-# Pipe any given argument to the minecraft server console
-mc_command() {
+# Pipe any given argument to the game server console
+game_command() {
${SUDO_CMD} screen -S "${SESSION_NAME}" -X stuff "`printf \"$*\r\"`"
}
+# Check whether the server is visited by a player otherwise shut it down
+idle_server_daemon() {
+ # This function is run within a screen session of the GAME_USER therefore SUDO_CMD can be omitted
+ if [[ $(whoami) != ${GAME_USER} ]]; then
+ >&2 echo "Somehow this hidden function was not executed by the ${GAME_USER} user."
+ >&2 echo "This should not have happend. Are you messing around with this script? :P"
+ exit 22
+ fi
+
+ # Time in seconds for which no player was on the server
+ no_player=0
+
+ while true; do
+ # Retry in ${CHECK_PLAYER_TIME} seconds
+ sleep ${CHECK_PLAYER_TIME}
+
+ screen -S "${SESSION_NAME}" -Q select . > /dev/null
+ if [[ $? -eq 0 ]]; then
+ # Game server is up and running
+ screen -S "${SESSION_NAME}" -X stuff "`printf \"list\r\"`"
+ # The list command prints a line containing the usernames after the last occurrence of ": "
+ # and since playernames may not contain this string the clean player-list can be easily retrieved.
+ if [[ $? -eq 0 && -z $(sleep 0.6; tail -n 1 "${LOGPATH}/latest.log" | sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' | sed 's/.*\: //' | tr -d '\n') ]]; then
+ # No player was seen on the server through list
+ no_player=$((no_player + CHECK_PLAYER_TIME))
+ # Stop the game server if no player was active for at least ${IDLE_IF_TIME}
+ if [[ "${no_player}" -ge "${IDLE_IF_TIME}" ]]; then
+ IDLE_SERVER="false" ${myname} stop
+ # Wait for game server to go down
+ for i in {1..100}; do
+ screen -S "${SESSION_NAME}" -Q select . > /dev/null
+ [[ $? -eq 1 ]] && break
+ [[ $i -eq 100 ]] && echo -e "An \e[39;1merror\e[0m occurred while trying to reset the idle_server!"
+ sleep 0.1
+ done
+ # Reset timer
+ no_player=0
+ # Game server is down, listen on port ${GAME_PORT} for incoming connections
+ echo "Netcat is listening on port ${GAME_PORT} for incoming connections..."
+ ${NETCAT_CMD} -v -l -p ${GAME_PORT}
+ [[ $? -eq 0 ]] && echo "Netcat caught an connection. The server is coming up again..."
+ IDLE_SERVER="false" ${myname} start
+ fi
+ elif [[ $? -eq 0 ]]; then
+ no_player=0
+ fi
+ else
+ # Reset timer
+ no_player=0
+ # Game server is down, listen on port ${GAME_PORT} for incoming connections
+ echo "Netcat is listening on port ${GAME_PORT} for incoming connections..."
+ ${NETCAT_CMD} -v -l -p ${GAME_PORT}
+ [[ $? -eq 0 ]] && echo "Netcat caught an connection. The server is coming up again..."
+ IDLE_SERVER="false" ${myname} start
+ fi
+ done
+}
+
# Start the server if it is not already running
server_start() {
+ # Start the game server
${SUDO_CMD} screen -S "${SESSION_NAME}" -Q select . > /dev/null
if [[ $? -eq 0 ]]; then
echo "A screen ${SESSION_NAME} session is already running. Please close it first."
else
- echo -en "Starting server... "
- ${SUDO_CMD} screen -dmS "${SESSION_NAME}" /bin/bash -c "cd '${SERVER_ROOT}'; java ${JAVA_PARMS} -jar '${SERVER_ROOT}/${MAIN_JAR}' nogui"
+ echo -en "Starting server..."
+ ${SUDO_CMD} screen -dmS "${SESSION_NAME}" /bin/bash -c "cd '${SERVER_ROOT}'; java ${JAVA_PARMS} -jar '${SERVER_ROOT}/${MAIN_EXECUTABLE}' nogui"
echo -e "\e[39;1m done\e[0m"
fi
+
+ if [[ "${IDLE_SERVER}" == "true" ]]; then
+ # Check for the availability of the netcat (nc) binaries
+ if [[ -z "${NETCAT_CMD}" ]]; then
+ >&2 echo "The netcat binaries are needed for suspending an idle server."
+ exit 12
+ fi
+
+ # Start the idle server daemon
+ ${SUDO_CMD} screen -S "${IDLE_SESSION_NAME}" -Q select . > /dev/null
+ if [[ $? -eq 0 ]]; then
+ ${SUDO_CMD} screen -S "${IDLE_SESSION_NAME}" -X quit
+ # Restart as soon as the idle_server_daemon has shut down completely
+ for i in {1..100}; do
+ ${SUDO_CMD} screen -S "${IDLE_SESSION_NAME}" -Q select . > /dev/null
+ [[ $? -eq 1 ]] && ${SUDO_CMD} screen -dmS "${IDLE_SESSION_NAME}" /bin/bash -c "${myname} idle_server_daemon" && break
+ [[ $i -eq 100 ]] && echo -e "An \e[39;1merror\e[0m occurred while trying to reset the idle_server!"
+ sleep 0.1
+ done
+ else
+ echo -en "Starting idle server daeomon..."
+ ${SUDO_CMD} screen -dmS "${IDLE_SESSION_NAME}" /bin/bash -c "${myname} idle_server_daemon"
+ echo -e "\e[39;1m done\e[0m"
+ fi
+ fi
}
# Stop the server gracefully by saving everything prior and warning the users
server_stop() {
+ # Quit the idle daemon
+ if [[ "${IDLE_SERVER}" == "true" ]]; then
+ # Check for the availability of the netcat (nc) binaries
+ if [[ -z "${NETCAT_CMD}" ]]; then
+ >&2 echo "The netcat binaries are needed for suspending an idle server."
+ exit 12
+ fi
+
+ ${SUDO_CMD} screen -S "${IDLE_SESSION_NAME}" -Q select . > /dev/null
+ if [[ $? -eq 0 ]]; then
+ echo -en "Stopping idle server daemon..."
+ ${SUDO_CMD} screen -S "${IDLE_SESSION_NAME}" -X quit
+ echo -e "\e[39;1m done\e[0m"
+ else
+ echo "The corresponding screen session for ${IDLE_SESSION_NAME} was already dead."
+ fi
+ fi
+
+ # Gracefully exit the game server
${SUDO_CMD} screen -S "${SESSION_NAME}" -Q select . > /dev/null
if [[ $? -eq 0 ]]; then
- mc_command save-all
- mc_command say "Server is going down in 10 seconds! HURRY UP WITH WATHEVER YOU ARE DOING!" # Warning the users
- echo -en "Server is going down in... "
- for i in $(seq 1 10); do
- mc_command say "down in... $(expr 10 - $i)"
- echo -n " $(expr 10 - $i)"
- sleep 1
+ # Game server is up and running, gracefully stop the server when there are still active players
+ ${SUDO_CMD} screen -S "${SESSION_NAME}" -X stuff "`printf \"list\r\"`"
+ # The list command prints a line containing the usernames after the last occurrence of ": "
+ # and since playernames may not contain this string the clean player-list can be easily retrieved.
+ if [[ $? -eq 0 && -z $(sleep 0.6; tail -n 1 "${LOGPATH}/latest.log" | sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' | sed 's/.*\: //' | tr -d '\n') ]]; then
+ # No player was seen on the server through list
+ echo -en "Server is going down..."
+ game_command stop
+ else
+ # Player(s) were seen on the server through list (or an error occurred)
+ # Warning the users through the server console
+ game_command say "Server is going down in 10 seconds! HURRY UP WITH WHATEVER YOU ARE DOING!"
+ game_command save-all
+ echo -en "Server is going down in..."
+ for i in {1..10}; do
+ game_command say "down in... $(expr 10 - $i)"
+ echo -n " $(expr 10 - $i)"
+ sleep 1
+ done
+ game_command stop
+ fi
+
+ # Finish as soon as the server has shut down completely
+ for i in {1..100}; do
+ ${SUDO_CMD} screen -S "${SESSION_NAME}" -Q select . > /dev/null
+ [[ $? -eq 1 ]] && echo -e "\e[39;1m done\e[0m" && break
+ [[ $i -eq 100 ]] && echo -e "\e[39;1m timed out\e[0m"
+ sleep 0.1
done
- mc_command stop
- echo -e "\e[39;1m done\e[0m"
else
echo "The corresponding screen session for ${SESSION_NAME} was already dead."
fi
@@ -75,13 +220,30 @@ server_stop() {
# Print whether the server is running and if so give some information about memory usage and threads
server_status() {
+ # Print status information about the idle daemon
+ if [[ "${IDLE_SERVER}" == "true" ]]; then
+ # Check for the availability of the netcat (nc) binaries
+ if [[ -z "${NETCAT_CMD}" ]]; then
+ >&2 echo "The netcat binaries are needed for suspending an idle server."
+ exit 12
+ fi
+
+ ${SUDO_CMD} screen -S "${IDLE_SESSION_NAME}" -Q select . > /dev/null
+ if [[ $? -eq 0 ]]; then
+ echo -e "Idle server daemon status:\e[39;1m running\e[0m"
+ else
+ echo -e "Idle server daemon status:\e[39;1m stopped\e[0m"
+ fi
+ fi
+
+ # Print status information for the game server
${SUDO_CMD} screen -S "${SESSION_NAME}" -Q select . > /dev/null
if [[ $? -eq 0 ]]; then
echo -e "Status:\e[39;1m running\e[0m"
# Calculating memory usage
- for p in $(${SUDO_CMD} pgrep -f "${MAIN_JAR}"); do
- ps -p${p} -O rss | tail -n1;
+ for p in $(${SUDO_CMD} pgrep -f "${MAIN_EXECUTABLE}"); do
+ ps -p${p} -O rss | tail -n 1;
done | gawk '{ count ++; sum += $2 }; END {count --; print "Number of processes =", count, "(screen, bash,", count-2, "x java)"; print "Total memory usage =", sum/1024, "MB" ;};'
else
echo -e "Status:\e[39;1m stopped\e[0m"
@@ -93,41 +255,40 @@ server_restart() {
${SUDO_CMD} screen -S "${SESSION_NAME}" -Q select . > /dev/null
if [[ $? -eq 0 ]]; then
server_stop
- sleep 0.1
server_start
else
server_start
fi
}
-# Backup the directories specified in $WORLDPATHS
+# Backup the directories specified in BACKUP_PATHS
backup_files() {
# Check for the availability of the tar binaries
which tar &> /dev/null
if [[ $? -ne 0 ]]; then
- echo "The tar binaries are needed for a backup."
- exit 2
+ >&2 echo "The tar binaries are needed for a backup."
+ exit 11
fi
echo "Starting backup..."
FILE="$(date +%Y_%m_%d_%H.%M.%S).tar.gz"
- ${SUDO_CMD} mkdir -p "${BACKUPPATH}"
+ ${SUDO_CMD} mkdir -p "${BACKUP_DEST}"
${SUDO_CMD} screen -S "${SESSION_NAME}" -Q select . > /dev/null
if [[ $? -eq 0 ]]; then
- mc_command save-off
- mc_command save-all
+ game_command save-off
+ game_command save-all
sync && wait
- ${SUDO_CMD} tar -C "${SERVER_ROOT}" -czf "${BACKUPPATH}/${FILE}" --totals ${WORLDPATHS} 2>&1 | grep -v "tar: Removing leading "
- mc_command save-on
+ ${SUDO_CMD} tar -C "${SERVER_ROOT}" -czf "${BACKUP_DEST}/${FILE}" --totals ${BACKUP_PATHS} 2>&1 | grep -v "tar: Removing leading "
+ game_command save-on
else
- ${SUDO_CMD} tar -C "${SERVER_ROOT}" -czf "${BACKUPPATH}/${FILE}" --totals ${WORLDPATHS} 2>&1 | grep -v "tar: Removing leading "
+ ${SUDO_CMD} tar -C "${SERVER_ROOT}" -czf "${BACKUP_DEST}/${FILE}" --totals ${BACKUP_PATHS} 2>&1 | grep -v "tar: Removing leading "
fi
echo -e "\e[39;1mbackup completed\e[0m\n"
echo -n "Only keeping the last ${KEEP_BACKUPS} backups and removing the other ones..."
- BACKUP_COUNT=$(for f in "${BACKUPPATH}"/[0-9_.]*; do echo ${f}; done | wc -l)
+ BACKUP_COUNT=$(for f in "${BACKUP_DEST}"/[0-9_.]*; do echo ${f}; done | wc -l)
if [[ $(expr ${BACKUP_COUNT} - ${KEEP_BACKUPS}) -gt 0 ]]; then
- ${SUDO_CMD} rm $(for f in "${BACKUPPATH}"/[0-9_.]*; do echo ${f}; done | head -n$(expr ${BACKUP_COUNT} - ${KEEP_BACKUPS}))
+ ${SUDO_CMD} rm $(for f in "${BACKUP_DEST}"/[0-9_.]*; do echo ${f}; done | head -n$(expr ${BACKUP_COUNT} - ${KEEP_BACKUPS}))
echo -e "\e[39;1m done\e[0m ($(expr ${BACKUP_COUNT} - ${KEEP_BACKUPS}) backup(s) pruned)"
else
echo -e "\e[39;1m done\e[0m (no backups pruned)"
@@ -139,14 +300,14 @@ backup_restore() {
# Check for the availability of the tar binaries
which tar &> /dev/null
if [[ $? -ne 0 ]]; then
- echo "The tar binaries are needed for a backup."
- exit 2
+ >&2 echo "The tar binaries are needed for a backup."
+ exit 11
fi
# Only allow the user to restore a backup if the server is down
${SUDO_CMD} screen -S "${SESSION_NAME}" -Q select . > /dev/null
if [[ $? -eq 0 ]]; then
- echo -e "The \e[39;1mserver should be down\e[0m in order to restore the world data."
+ >&2 echo -e "The \e[39;1mserver should be down\e[0m in order to restore the world data."
exit 3
fi
@@ -154,7 +315,7 @@ backup_restore() {
if [[ $# -lt 1 ]]; then
echo "Please enter the corresponding number for the backup to be restored: "
i=1
- for f in "${BACKUPPATH}"/[0-9_.]*; do
+ for f in "${BACKUP_DEST}"/[0-9_.]*; do
echo -e " \e[39;1m$i)\e[0m\t$f"
i=$((i+1))
done
@@ -166,16 +327,16 @@ backup_restore() {
# Interpeting the input
if [[ $user_choice =~ ^-?[0-9]+$ ]]; then
n=1
- for f in "${BACKUPPATH}"/[0-9_.]*; do
+ for f in "${BACKUP_DEST}"/[0-9_.]*; do
[[ ${n} -eq $user_choice ]] && FILE="$f"
n=$((n+1))
done
if [[ -z $FILE ]]; then
- echo -e "\e[39;1mFailed\e[0m to interpret your input. Please enter the digit of the presented options."
+ >&2 echo -e "\e[39;1mFailed\e[0m to interpret your input. Please enter the digit of the presented options."
exit 5
fi
else
- echo -e "\e[39;1mFailed\e[0m to interpret your input. Please enter a valid digit for one of the presented options."
+ >&2 echo -e "\e[39;1mFailed\e[0m to interpret your input. Please enter a valid digit for one of the presented options."
exit 6
fi
elif [[ $# -eq 1 ]]; then
@@ -183,17 +344,17 @@ backup_restore() {
if [[ -f "$1" ]]; then
FILE="$1"
else
- if [[ -f "${BACKUPPATH}"/"$1" ]]; then
- FILE="${BACKUPPATH}"/"$1"
+ if [[ -f "${BACKUP_DEST}"/"$1" ]]; then
+ FILE="${BACKUP_DEST}"/"$1"
else
- echo -e "Sorry, but '$1', is \e[39;1mnot a valid file\e[0m, neither in your current directory nor in the backup folder."
+ >&2 echo -e "Sorry, but '$1', is \e[39;1mnot a valid file\e[0m, neither in your current directory nor in the backup folder."
exit 4
fi
fi
elif [[ $# -gt 1 ]]; then
- echo -e "\e[39;1mToo many arguments.\e[0m Please pass only the filename for the world data as an argument."
- echo "Or alternatively no arguments at all to chose from a list of available backups."
- exit 1
+ >&2 echo -e "\e[39;1mToo many arguments.\e[0m Please pass only the filename for the world data as an argument."
+ >&2 echo "Or alternatively no arguments at all to chose from a list of available backups."
+ exit 7
fi
echo "Restoring backup..."
@@ -205,25 +366,24 @@ backup_restore() {
fi
}
-# Run the given comman at the minecraft server console
+# Run the given comman at the game server console
server_command() {
if [[ $# -lt 1 ]]; then
- echo "No server command specified. Try 'help' for a list of commands."
+ >&2 echo "No server command specified. Try 'help' for a list of commands."
exit 1
fi
${SUDO_CMD} screen -S "${SESSION_NAME}" -Q select . > /dev/null
if [[ $? -eq 0 ]]; then
- sleep 0.1s &
- sleep_pid=$!
- mc_command "$@" &
- tail -f --pid=${sleep_pid} -n 0 "${LOGPATH}/latest.log"
+ ${SUDO_CMD} sleep 0.3 & tail -f --pid=$! -s 0.1 -n 0 "${LOGPATH}/latest.log" &
+ game_command "$@"
+ wait
else
echo "There is no ${SESSION_NAME} session to connect to."
fi
}
-# Enter the screen minecraft session
+# Enter the screen game session
server_console() {
${SUDO_CMD} screen -S "${SESSION_NAME}" -Q select . > /dev/null
if [[ $? -eq 0 ]]; then
@@ -236,17 +396,17 @@ server_console() {
# Help function, no arguments required
help() {
cat <<-EOF
- This script was design to easily control any minecraft server. Quite every parameter for a given
- minecraft server derivative can be altered by editing the variables in the configuration file.
+ This script was design to easily control any ${game} server. Quite every parameter for a given
+ ${game} server derivative can be altered by editing the variables in the configuration file.
- Usage: $myname {start|stop|status|backup|restore|command <command>|console}
- start Start the minecraft server
- stop Stop the minecraft server
- restart Restart the minecraft server
+ Usage: ${myname} {start|stop|status|backup|restore|command <command>|console}
+ start Start the ${game} server
+ stop Stop the ${game} server
+ restart Restart the ${game} server
status Print some status information
backup Backup the world data
restore [filename] Restore the world data from a backup
- command <command> Run the given comman at the minecraft server console
+ command <command> Run the given comman at the ${game} server console
console Enter the server console through a screen session
Copyright (c) Gordian Edenhofer <gordian.edenhofer@gmail.com>
@@ -286,8 +446,14 @@ case "$1" in
backup_restore "${@:2}"
;;
+ idle_server_daemon)
+ # This shell be a hidden function which should only be invoced internally
+ idle_server_daemon
+ ;;
+
*|-h|--help)
help
+ exit 0
esac
exit 0