diff options
author | BuildTools | 2016-04-27 15:49:37 -0700 |
---|---|---|
committer | BuildTools | 2016-04-27 15:49:37 -0700 |
commit | f52bcd11078cf46c294dc14965694f29134bd79d (patch) | |
tree | fa07394842b28ac1be83cfa8b5516ff3c9d261c1 | |
parent | a567faf23b731bb2736d8754e8ff42709983a096 (diff) | |
download | aur-f52bcd11078cf46c294dc14965694f29134bd79d.tar.gz |
New config / run script updates from edh
-rw-r--r-- | .SRCINFO | 19 | ||||
-rwxr-xr-x | PKGBUILD | 60 | ||||
-rw-r--r-- | spigot-backup.service | 2 | ||||
-rw-r--r-- | spigot.conf | 19 | ||||
-rwxr-xr-x | spigot.install | 66 | ||||
-rwxr-xr-x | spigot.service | 4 | ||||
-rwxr-xr-x | spigot.sh | 324 |
7 files changed, 346 insertions, 148 deletions
@@ -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 @@ -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 4eda131909d7..9d64e48bf5c9 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 7d2fe6303713..ebe90d70c615 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 9422066f97bc..27d960b031b6 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 7178066f2f6b..99406f0b2157 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 697eb9ecfcf1..dc4f0ed88320 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 |