From f312efaac7a9714c82cd506027c342a41e66e211 Mon Sep 17 00:00:00 2001 From: Gordian Edenhofer Date: Mon, 29 Feb 2016 21:35:38 +0100 Subject: [PATCH] Upgpkg: 1.9-1 Add suspending capability for the minecraft server through the control script and an additional screen session which listens on the same port with netcat. * Update .conf accordingly * IDLE_SERVER can be either true or false * The default is no idle server * Choose an available netcat flavor automatically Variable renaming in .install. Notify the user of kept directories on post_remove and alter ownership to root before removing the game user. Print error messages to stderr. --- .SRCINFO | 22 ++-- PKGBUILD | 18 +-- minecraft-server.install | 44 +++---- minecraftd-backup.service | 3 + minecraftd.conf | 11 +- minecraftd.service | 3 + minecraftd.sh | 266 ++++++++++++++++++++++++++++---------- 7 files changed, 255 insertions(+), 112 deletions(-) diff --git a/.SRCINFO b/.SRCINFO index 61bc151..20c7746 100644 --- a/.SRCINFO +++ b/.SRCINFO @@ -1,9 +1,7 @@ -# Generated by mksrcinfo v8 -# Mon Feb 1 20:55:13 UTC 2016 pkgbase = minecraft-server pkgdesc = Minecraft server unit files, script, and jar - pkgver = 1.8.9 - pkgrel = 4 + pkgver = 1.9 + pkgrel = 1 url = http://minecraft.net/ install = minecraft-server.install arch = any @@ -13,23 +11,23 @@ pkgbase = minecraft-server depends = sudo depends = bash optdepends = tar: needed in order to create world backups + optdepends = netcat: required in order to suspend an idle server conflicts = minecraft-server-systemd conflicts = minecraft-canary - noextract = minecraft_server.1.8.9.jar + noextract = minecraft_server.1.9.jar options = !strip backup = etc/conf.d/minecraft - source = https://s3.amazonaws.com/Minecraft.Download/versions/1.8.9/minecraft_server.1.8.9.jar + source = https://s3.amazonaws.com/Minecraft.Download/versions/1.9/minecraft_server.1.9.jar source = minecraftd-backup.service source = minecraftd-backup.timer source = minecraftd.service source = minecraftd.conf source = minecraftd.sh - md5sums = 3acbaef956308c805e8e2d0a03a737e9 - md5sums = 2cf6cdf65e0ed6aa6d452943b1e84357 + md5sums = ff68834eee875bcf367422c67673207c + md5sums = f75c76446f96311563e87fc688148501 md5sums = fef6fadd0739ae03ff71ba61025be207 - md5sums = 5ed78e366146e47f8498347e93ad5423 - md5sums = 9f56e2a4f435e642a0b183c6bff5c206 - md5sums = dcf4f4b4de06c6ff3b5445539c4e3d42 + md5sums = cab358c32dd0d4d2463e60ee2996f658 + md5sums = 54438e0c47cc5083e0a4376688b46092 + md5sums = 59bf34cc34f61fc36824620bf5e7f2fd pkgname = minecraft-server - diff --git a/PKGBUILD b/PKGBUILD index 61ed104..4eb1d6f 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,15 +1,17 @@ # Maintainer: Gordian Edenhofer # Contributer: Philip Abernethy +# Contributer: sowieso pkgname=minecraft-server -pkgver=1.8.9 -pkgrel=4 +pkgver=1.9 +pkgrel=1 pkgdesc="Minecraft server unit files, script, and jar" arch=('any') url="http://minecraft.net/" license=('custom') depends=('java-runtime-headless' 'screen' 'sudo' 'bash') -optdepends=('tar: needed in order to create world backups') +optdepends=("tar: needed in order to create world backups" + "netcat: required in order to suspend an idle server") conflicts=('minecraft-server-systemd' 'minecraft-canary') options=(!strip) install=${pkgname}.install @@ -21,12 +23,12 @@ source=("https://s3.amazonaws.com/Minecraft.Download/versions/${pkgver}/minecraf "minecraftd.conf" "minecraftd.sh") noextract=("minecraft_server.${pkgver}.jar") -md5sums=('3acbaef956308c805e8e2d0a03a737e9' - '2cf6cdf65e0ed6aa6d452943b1e84357' +md5sums=('ff68834eee875bcf367422c67673207c' + 'f75c76446f96311563e87fc688148501' 'fef6fadd0739ae03ff71ba61025be207' - '5ed78e366146e47f8498347e93ad5423' - '9f56e2a4f435e642a0b183c6bff5c206' - 'dcf4f4b4de06c6ff3b5445539c4e3d42') + 'cab358c32dd0d4d2463e60ee2996f658' + '54438e0c47cc5083e0a4376688b46092' + '59bf34cc34f61fc36824620bf5e7f2fd') package() { install -Dm644 minecraftd.conf "${pkgdir}/etc/conf.d/minecraft" diff --git a/minecraft-server.install b/minecraft-server.install index 961988c..96343b4 100644 --- a/minecraft-server.install +++ b/minecraft-server.install @@ -1,31 +1,31 @@ -USER="minecraft" -SERVER_ROOT="/srv/minecraft" +_user="minecraft" +_server_root="/srv/minecraft" 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: 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 minecraft script under /usr/bin/minecraftd 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/minecraft 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: 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 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" @@ -44,15 +44,15 @@ pre_remove() { } 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 - fi - 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" + [[ -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/minecraft" ]] && echo -e "\e[34;1m==>\e[39;1m NOTE: Your configuration file /etc/conf.d/minecraft 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} + fi } diff --git a/minecraftd-backup.service b/minecraftd-backup.service index ff2085e..20fae70 100644 --- a/minecraftd-backup.service +++ b/minecraftd-backup.service @@ -4,7 +4,10 @@ After=local-fs.target [Service] Type=forking +EnvironmentFile=/etc/conf.d/minecraft ExecStart=/usr/bin/minecraftd backup +USER=$MC_USER +GROUP=$MC_USER [Install] WantedBy=multi-user.target diff --git a/minecraftd.conf b/minecraftd.conf index c517a2e..40f1aec 100644 --- a/minecraftd.conf +++ b/minecraftd.conf @@ -11,8 +11,17 @@ MC_USER="minecraft" MAIN_JAR="minecraft_server.jar" SESSION_NAME="minecraft" -# 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/minecraftd.service b/minecraftd.service index 17e18af..45bae6e 100644 --- a/minecraftd.service +++ b/minecraftd.service @@ -4,8 +4,11 @@ After=local-fs.target network.target [Service] Type=forking +EnvironmentFile=/etc/conf.d/minecraft ExecStart=/usr/bin/minecraftd start ExecStop=/usr/bin/minecraftd stop +USER=$MC_USER +GROUP=$MC_USER [Install] WantedBy=multi-user.target diff --git a/minecraftd.sh b/minecraftd.sh index 8743bd7..a44d84e 100755 --- a/minecraftd.sh +++ b/minecraftd.sh @@ -1,72 +1,177 @@ #!/bin/bash -source /etc/conf.d/minecraft || echo "Could not source /etc/conf.d/minecraft" - -# General rule for the variable-naming-schema: -# Variables in capital letters may be passed through the command line others not. - -# You may use this script for any minecraft server of your choice, just alter the config file -SERVER_ROOT="${SERVER_ROOT:-/srv/minecraft}" -BACKUPPATH="${BACKUPPATH:-/srv/minecraft/backup}" -LOGPATH="${LOGPATH:-/srv/minecraft/logs}" -WORLDPATHS="${WORLDPATHS:-world}" -KEEP_BACKUPS="${KEEP_BACKUPS:-10}" -MC_USER="${MC_USER:-minecraft}" -MAIN_JAR="${MAIN_JAR:-minecraft_server.jar}" -SESSION_NAME="${SESSION_NAME:-minecraft}" - -# 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="minecraftd" +declare -r game="minecraft" + +# 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. + +# 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/${game}" +[[ ! -z "${BACKUP_DEST}" ]] && declare -r BACKUP_DEST=${BACKUP_DEST} || BACKUP_DEST="/srv/${game}/backup" +[[ ! -z "${LOGPATH}" ]] && declare -r LOGPATH=${LOGPATH} || LOGPATH="/srv/${game}/logs" +[[ ! -z "${BACKUP_PATHS}" ]] && declare -r BACKUP_PATHS=${BACKUP_PATHS} || BACKUP_PATHS="world" +[[ ! -z "${KEEP_BACKUPS}" ]] && declare -r KEEP_BACKUPS=${KEEP_BACKUPS} || KEEP_BACKUPS="10" +[[ ! -z "${GAME_USER}" ]] && declare -r GAME_USER=${GAME_USER} || GAME_USER="minecraft" +[[ ! -z "${MAIN_EXECUTABLE}" ]] && declare -r MAIN_EXECUTABLE=${MAIN_EXECUTABLE} || MAIN_EXECUTABLE="minecraft_server.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}" ]] && declare -r 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/minecraft || echo "Could not source /etc/conf.d/minecraft" # 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 + 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 "player_delimiter" in awk print needs to be 6 for the spigot server + # since the according information is contained in the 6th not in th 4th column + if [[ -z $(tail -n 1 "${LOGPATH}/latest.log" | awk '{ print $4 }') ]]; 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} + [[ "${no_player}" -ge "${IDLE_IF_TIME}" ]] && IDLE_SERVER="false" ${myname} stop + else + no_player=0 + # Retry in ${CHECK_PLAYER_TIME} seconds + sleep ${CHECK_PLAYER_TIME} + fi + else + # 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 ${GAME_PORT} + echo "Netcat caught an connection. The server is coming up again...." + IDLE_SERVER="false" ${myname} start + sleep ${CHECK_PLAYER_TIME} + 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" + ${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 + echo "An idles server screen session called ${IDLE_SESSION_NAME} is already running. Please close it first." + 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 + else + # Though IDLE_SERVER is not set to true it could still be running and just have not noticed that the + # server was started, e.g. by manually triggering server_start again. Therefore reset the idle 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 + fi + ${SUDO_CMD} screen -dmS "${IDLE_SESSION_NAME}" /bin/bash -c "${myname} idle_server_daemon" + 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 + game_command save-all + game_command say "Server is going down in 10 seconds! HURRY UP WITH WHATEVER 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)" + game_command say "down in... $(expr 10 - $i)" echo -n " $(expr 10 - $i)" sleep 1 done - mc_command stop + game_command stop echo -e "\e[39;1m done\e[0m" else echo "The corresponding screen session for ${SESSION_NAME} was already dead." @@ -75,12 +180,29 @@ 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 + for p in $(${SUDO_CMD} pgrep -f "${MAIN_EXECUTABLE}"); do ps -p${p} -O rss | tail -n1; 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 @@ -100,34 +222,34 @@ server_restart() { 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 +261,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 +276,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 +288,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 +305,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,10 +327,10 @@ 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 @@ -216,14 +338,14 @@ server_command() { if [[ $? -eq 0 ]]; then sleep 0.1s & sleep_pid=$! - mc_command "$@" & + game_command "$@" & tail -f --pid=${sleep_pid} -n 0 "${LOGPATH}/latest.log" 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 +358,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 |console} - start Start the minecraft server - stop Stop the minecraft server - restart Restart the minecraft server + Usage: ${myname} {start|stop|status|backup|restore|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 Run the given comman at the minecraft server console + command Run the given comman at the ${game} server console console Enter the server console through a screen session Copyright (c) Gordian Edenhofer @@ -286,8 +408,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