masa- icon

mc_common_functions.sh (2018-10-13)

masa- | PRO | 06/06/20 08:02:55 PM UTC | 0 ⭐ | 588 👁️ | Never ⏰ | []
Bash |

31.95 KB

|

None

|

0 👍

/

0 👎

#!/bin/bash
# Initial version from Minecraft wiki
# Heavily modified, customized and expanded by masa
# version x.x.x 2018-10-13 (YYYY-MM-DD)
 
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
 
as_user() {
    ME=`whoami`
 
    if [ ${ME} == ${USERNAME} ] ; then
        bash -c "${1}"
    else
        su - ${USERNAME} -c "${1}"
    fi
}
 
 
mc_start() {
    L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
    L_PREFIX="${L_TIMESTAMP}"
 
    # Check that the server is not already running
    if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
    then
        echo "${L_PREFIX} [WARNING] mc_start(): ${SERVICE} is already running" | tee -a ${EVENT_LOG_FILE}
    else
        echo "${L_PREFIX} [INFO] mc_start(): Starting ${SERVICE}..." | tee -a ${EVENT_LOG_FILE}
 
        if [ "${USE_TEMP_LOCATION}" = "true" ]
        then
            # Copy the save files rom the actual game directory to the run-time location inside /tmp
            copy_save_files_from_game_dir_to_tmp
            local RET=$?
 
            if [ $RET -ne 0 ]; then
                echo "${L_TIMESTAMP} [ERROR] mc_start(): Failed to copy over the save files!" | tee -a ${EVENT_LOG_FILE}
                exit 1
            fi
        fi
 
        # Start the server process
        as_user "cd ${INSTANCE_PATH} && screen -dmS ${SCREEN_SESSION} ${INVOCATION}"
        sleep ${POST_START_DELAY}
 
        # Verify that the server process was started successfully, by checking a few times in a delayed loop
        COUNTER=0
 
        while [ $COUNTER -lt ${START_GRACE_DELAY} ]
        do
            if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
            then
                L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
                L_PREFIX="${L_TIMESTAMP}"
 
                echo "${L_PREFIX} [INFO] mc_start(): ${SERVICE} is now running" | tee -a ${EVENT_LOG_FILE}
 
                # Create the state file to indicate that the server is/should be running
                as_user "touch ${STATE_FILE}"
 
                # Disable automatic saving?
                if [ ${START_TO_DISABLE_AUTOSAVE_DELAY} -ge 0 ]
                then
                    sleep ${START_TO_DISABLE_AUTOSAVE_DELAY}
                    mc_saveoff
                fi
 
                break
            fi
 
            sleep 1
 
            ((COUNTER += 1))
        done
 
        # If the loop counter hit the max value, the process was not started successfully
        if [ ${COUNTER} -ge ${START_GRACE_DELAY} ]
        then
            L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
            L_PREFIX="${L_TIMESTAMP}"
 
            echo "${L_PREFIX} [ERROR] mc_start(): Could not start ${SERVICE}" | tee -a ${EVENT_LOG_FILE}
        fi
    fi
}
 
 
mc_stop() {
    L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
    L_PREFIX="${L_TIMESTAMP}"
 
    # Check that the process is running
    if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
    then
        echo "${L_PREFIX} [INFO] mc_stop(): Stopping ${SERVICE}" | tee -a ${EVENT_LOG_FILE}
 
        if [ ${SAVEALL_STOP_INTERVAL} -ge 0 ]; then
            if [ "${1}" = "broadcast" ]; then
                as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"say §dSERVER SHUTTING DOWN NOW. Saving the map...\"\015'"
            fi
 
            as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"save-all\"\015'"
            sleep ${SAVEALL_STOP_INTERVAL}
        else
            if [ "${1}" = "broadcast" ]; then
                as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"say §dSERVER SHUTTING DOWN NOW!!\"\015'"
                sleep 3
            fi
        fi
 
        as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"stop\"\015'"
        sleep ${POST_STOP_DELAY}
 
        # Check if the process was successfully stopped
        COUNTER=0
        while [ ${COUNTER} -lt ${STOP_GRACE_DELAY} ]; do
 
            if ! pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
            then
                # Remove the state file to indicate that the server has been stopped gracefully
                as_user "rm ${STATE_FILE} > /dev/null 2>&1"
 
                L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
                L_PREFIX="${L_TIMESTAMP}"
                echo "${L_PREFIX} [INFO] mc_stop(): ${SERVICE} has been stopped" | tee -a ${EVENT_LOG_FILE}
 
                if [ "${USE_TEMP_LOCATION}" = "true" ]
                then
                    # Copy the save files from the temp directory (in RAM) into the actual server directory
                    copy_save_files_from_tmp_to_game_dir
                    local RET=$?
 
                    # If copying the save file succeeded, and this is not a restart, then remove the temp files
                    if [ $RET -eq 0 ] && [ "$1" != "true" ]
                    then
                        remove_save_files_from_tmp_location
                    fi
                fi
 
                break
            fi
 
            sleep 1
 
            ((COUNTER += 1))
        done
 
        if [ ${COUNTER} -ge ${STOP_GRACE_DELAY} ]
        then
            L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
            L_PREFIX="${L_TIMESTAMP}"
 
            echo "${L_PREFIX} [ERROR] mc_stop(): ${SERVICE} could not be stopped" | tee -a ${EVENT_LOG_FILE}
        fi
    else
        echo "${L_PREFIX} [WARNING] mc_stop(): ${SERVICE} was not running" | tee -a ${EVENT_LOG_FILE}
    fi
}
 
 
mc_restart() {
    # Use the arguments as override delay values, if they exist
    if [ -n "${1}" ]
    then
        RESTART_FIRST_WARNING=${1}
 
        if [ -n "${2}" ]
        then
            RESTART_LAST_WARNING=${2}
        fi
    fi
 
    # Check if the server process is running, and broadcast warning messages before stopping the server
    if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
    then
        if [ ${RESTART_FIRST_WARNING} -gt ${RESTART_LAST_WARNING} ]
        then
            as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"say §dSERVER RESTARTING IN ${RESTART_FIRST_WARNING} SECONDS\"\015'"
            ((DELAY = ${RESTART_FIRST_WARNING} - ${RESTART_LAST_WARNING}))
            sleep ${DELAY}
        fi
 
        as_user "screen -p 0 -S $SCREEN_SESSION -X eval 'stuff \"say §dSERVER RESTARTING IN ${RESTART_LAST_WARNING} SECONDS\"\015'"
        sleep ${RESTART_LAST_WARNING}
 
        L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
        L_PREFIX="${L_TIMESTAMP}"
        echo "${L_PREFIX} [INFO] mc_restart(): Stopping ${SERVICE}" | tee -a ${EVENT_LOG_FILE}
 
        mc_stop "true"
 
        if ! pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
        then
            L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
            L_PREFIX="${L_TIMESTAMP}"
            echo "${L_PREFIX} [INFO] mc_restart(): ${SERVICE} has been stopped" | tee -a ${EVENT_LOG_FILE}
        fi
    fi
 
    # (Re-)Start the server
    if ! pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
    then
        L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
        L_PREFIX="${L_TIMESTAMP}"
        echo "${L_PREFIX} [INFO] mc_restart(): (Re-)starting ${SERVICE}..." | tee -a ${EVENT_LOG_FILE}
 
        mc_start
 
        L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
        L_PREFIX="${L_TIMESTAMP}"
 
        if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
        then
            echo "${L_PREFIX} [INFO] mc_restart(): ${SERVICE} is now running" | tee -a ${EVENT_LOG_FILE}
        else
            echo "${L_PREFIX} [ERROR] mc_restart(): Could not start ${SERVICE}" | tee -a ${EVENT_LOG_FILE}
        fi
 
    else
        echo "${L_PREFIX} [ERROR] mc_restart(): ${SERVICE} could not be stopped" | tee -a ${EVENT_LOG_FILE}
    fi
}
 
 
mc_restart_if_up() {
    # Use the arguments as override delay values, if they exist
    if [ -n "${1}" ]
    then
        RESTART_FIRST_WARNING=${1}
 
        if [ -n "${2}" ]
        then
            RESTART_LAST_WARNING=${2}
        fi
    fi
 
    # First check if the server is supposed to be running
    if [ -f "${STATE_FILE}" ]
    then
        # Check if the server process is running, and broadcast warning messages before stopping the server
        if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
        then
            if [ ${RESTART_FIRST_WARNING} -gt ${RESTART_LAST_WARNING} ]
            then
                as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"say §dSERVER RESTARTING IN ${RESTART_FIRST_WARNING} SECONDS\"\015'"
                ((DELAY = ${RESTART_FIRST_WARNING} - ${RESTART_LAST_WARNING}))
                sleep ${DELAY}
            fi
 
            as_user "screen -p 0 -S $SCREEN_SESSION -X eval 'stuff \"say §dSERVER RESTARTING IN ${RESTART_LAST_WARNING} SECONDS\"\015'"
            sleep ${RESTART_LAST_WARNING}
 
            L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
            L_PREFIX="${L_TIMESTAMP}"
            echo "${L_PREFIX} [INFO] mc_restart_if_up(): Stopping ${SERVICE}" | tee -a ${EVENT_LOG_FILE}
 
            mc_stop "true"
        fi
 
        # The server was running and was successfully stopped, or at least is supposed to be running. Now we start it up again.
        if ! pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
        then
            L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
            L_PREFIX="${L_TIMESTAMP}"
 
            echo "${L_PREFIX} [INFO] mc_restart_if_up(): ${SERVICE} has been stopped" | tee -a ${EVENT_LOG_FILE}
            echo "${L_PREFIX} [INFO] mc_restart_if_up(): Restarting ${SERVICE}..." | tee -a ${EVENT_LOG_FILE}
 
            mc_start
 
            L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
            L_PREFIX="${L_TIMESTAMP}"
 
            if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
            then
                echo "${L_PREFIX} [INFO] mc_restart_if_up(): ${SERVICE} is now running" | tee -a ${EVENT_LOG_FILE}
            else
                echo "${L_PREFIX} [ERROR] mc_restart_if_up(): Could not start ${SERVICE}" | tee -a ${EVENT_LOG_FILE}
            fi
 
        else
            echo "${L_PREFIX} [ERROR] mc_restart_if_up(): ${SERVICE} could not be stopped" | tee -a ${EVENT_LOG_FILE}
        fi
#   else
#       L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
#       L_PREFIX="${L_TIMESTAMP}"
#       echo "${L_PREFIX} [WARNING] mc_restart_if_up(): ${SERVICE} was not running" | tee -a ${EVENT_LOG_FILE}
    fi
}
 
 
mc_saveoff() {
    if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
    then
        if [ "${1}" = "broadcast" ];
        then
            as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"say §dServer going read-only...\"\015'"
        fi
 
        as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"save-off\"\015'"
    fi
}
 
 
mc_saveon() {
    if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
    then
        if [ "${1}" = "broadcast" ];
        then
            as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"say §dServer going read-write...\"\015'"
        fi
 
        as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"save-on\"\015'"
    fi
}
 
 
mc_saveall() {
    if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
    then
        if [ "${1}" = "broadcast" ];
        then
            as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"say §dSaving the map...\"\015'"
        fi
 
        as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"save-all\"\015'"
        sleep ${POST_SAVEALL_DELAY}
    fi
}
 
 
mc_sync() {
    if [ "${USE_TEMP_LOCATION}" = "true" ]; then
        # Check if the server process is running
        if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
        then
            mc_say "§dSyncing world data to disk, server going read-only"
            mc_saveoff
 
            if [ ${SAVEALL_BACKUP_INTERVAL} -ge 0 ]; then
                mc_saveall
                sleep ${SAVEALL_BACKUP_INTERVAL}
            else
                sleep 2
            fi
 
            # Copy the save files from the temp directory (in RAM) into the actual server directory
            copy_save_files_from_tmp_to_game_dir
 
            mc_say "§dSyncing world data to disk finished, server going read-write"
            mc_saveon
        # Server not running, but the temp path exists
        elif [ -e "${WORLD_PATH_TMP}" ]; then
            # Copy the save files from the temp directory (in RAM) into the actual server directory
            copy_save_files_from_tmp_to_game_dir
        fi
    fi
}
 
 
copy_save_files_from_game_dir_to_tmp() {
    L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
 
    if [ -z "${WORLD_PATH_TMP}" ] || [ -z "${WORLD_PATH_REAL}" ] || [ -z "${WORLD_PATH_SYMLINK}" ]
    then
        echo "Empty real or temp world path, or world path symlink name!"
        exit 1
    fi
 
    # Make the necessary temporary directories
    if [ ! -d "${WORLD_PATH_TMP}" ]
    then
        echo "${L_TIMESTAMP} [INFO] copy_save_files_from_game_dir_to_tmp(): Creating the temporary save directory '${WORLD_PATH_TMP}'" | tee -a ${EVENT_LOG_FILE}
        as_user "mkdir -p ${WORLD_PATH_TMP} > /dev/null 2>&1"
        as_user "chmod 1777 ${WORLD_PATH_TMP}"
    fi
 
    # The symlink does not point to the temp directory
    # (which means that it likely points to the real directory on disk, see remove_save_files_from_tmp_location())
    if [ -h "${WORLD_PATH_SYMLINK}" ] && [ `readlink -f ${WORLD_PATH_SYMLINK}` != "${WORLD_PATH_TMP}" ]
    then
        as_user "rm ${WORLD_PATH_SYMLINK} > /dev/null 2>&1"
    fi
 
    # No symlink present
    if [ ! -e "${WORLD_PATH_SYMLINK}" ]
    then
        echo "${L_TIMESTAMP} [INFO] copy_save_files_from_game_dir_to_tmp(): (Re-)Creating a symlink for the world directory to ${WORLD_PATH_TMP}" | tee -a ${EVENT_LOG_FILE}
        as_user "ln -s ${WORLD_PATH_TMP} ${WORLD_PATH_SYMLINK} > /dev/null 2>&1"
    fi
 
    echo "${L_TIMESTAMP} [INFO] copy_save_files_from_game_dir_to_tmp(): Going to copy the save files to the temp directory..." | tee -a ${EVENT_LOG_FILE}
 
    # Copy the save files from the "real save path" on disk to the temporary location (in RAM).
    # Note: -u to only copy newer files!
    as_user "rsync -au ${WORLD_PATH_REAL}/ ${WORLD_PATH_TMP} > /dev/null 2>&1"
    #as_user "rsync -auhv ${WORLD_PATH_REAL}/ ${WORLD_PATH_TMP}"
    local RET=$?
 
    L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
 
    if [ $RET -ne 0 ]; then
        echo "${L_TIMESTAMP} [ERROR] copy_save_files_from_game_dir_to_tmp(): Failed to copy over the save files" | tee -a ${EVENT_LOG_FILE}
        return 1
    else
        echo "${L_TIMESTAMP} [INFO] copy_save_files_from_game_dir_to_tmp(): Done copying files" | tee -a ${EVENT_LOG_FILE}
    fi
}
 
 
copy_save_files_from_tmp_to_game_dir() {
    L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
    echo "${L_TIMESTAMP} [INFO] copy_save_files_from_tmp_to_game_dir(): Going to copy the save files from the temp directory to the instance directory" | tee -a ${EVENT_LOG_FILE}
 
    if [ -z "${WORLD_PATH_TMP}" ] || [ -z "${WORLD_PATH_REAL}" ]
    then
        echo "EMPTY PATH"
        exit 1
    fi
 
    if [ ! -e "${WORLD_PATH_TMP}" ]
    then
        echo "${L_TIMESTAMP} [INFO] copy_save_files_from_tmp_to_game_dir: temp directory '${WORLD_PATH_TMP}' does not exist, nothing to do"
        return 0
    fi
 
 
    # Sync any changed files from the temp location to the real save path (the -u flag only copies newer files)
    as_user "rsync -au ${WORLD_PATH_TMP}/ ${WORLD_PATH_REAL} > /dev/null"
    #as_user "rsync -auhv ${WORLD_PATH_TMP}/ ${WORLD_PATH_REAL}"
    local RET=$?
 
    L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
 
    if [ $RET -ne 0 ]; then
        echo "${L_TIMESTAMP} [INFO] copy_save_files_from_tmp_to_game_dir(): Error copying save files!" | tee -a ${EVENT_LOG_FILE}
        return 1
    else
        echo "${L_TIMESTAMP} [INFO] copy_save_files_from_tmp_to_game_dir(): Done copying files" | tee -a ${EVENT_LOG_FILE}
    fi
}
 
 
remove_save_files_from_tmp_location() {
    if [ -n ${INSTANCE_PATH_TMP} ]
    then
        L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
        echo "${L_TIMESTAMP} [INFO] remove_save_files_from_tmp_location(): Removing the save files from the temp directory..." | tee -a ${EVENT_LOG_FILE}
 
        as_user "rm -r --preserve-root ${INSTANCE_PATH_TMP} > /dev/null"
 
        L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
        echo "${L_TIMESTAMP} [INFO] remove_save_files_from_tmp_location(): Done removing files" | tee -a ${EVENT_LOG_FILE}
 
        # World path is a symlink
        #if [ -h "${WORLD_PATH_SYMLINK}" ]
        #then
        #   echo "${L_TIMESTAMP} [INFO] remove_save_files_from_tmp_location(): Changing the symlink to point to the real world" | tee -a ${EVENT_LOG_FILE}
        #   as_user "rm ${WORLD_PATH_SYMLINK} > /dev/null 2>&1"
        #   as_user "cd ${INSTANCE_PATH}"
        #   local WORLDNAME=`basename ${WORLD_PATH_REAL}`
        #   as_user "ln -s ${WORLDNAME} ${WORLD_PATH_SYMLINK} > /dev/null 2>&1"
        #fi
    fi
}
 
 
mc_backup() {
    TIMESTAMP_TAR=`date '+%Y-%m-%d_%H.%M.%S'`
    TIMESTAMP_GIT=`date '+%Y-%m-%d %H:%M'`
 
    if [ "${USE_TEMP_LOCATION}" = "true" ] && [ -e "${WORLD_PATH_TMP}" ]
    then
        # Copy the save files from the temp directory (in RAM) into the actual server directory
        copy_save_files_from_tmp_to_game_dir
        local RET=$?
 
        if [ $RET -ne 0 ]; then
            L_PREFIX=`date "+%Y-%m-%d %H:%M:%S"`
            echo "${L_PREFIX} [INFO] mc_backup(): Failed to copy save files from temp to game dir for instance '${INSTANCE}'" | tee -a ${EVENT_LOG_FILE}
            echo "${L_PREFIX} [INFO] mc_backup(): Failed to copy save files from temp to game dir for instance '${INSTANCE}'" | tee -a ${BACKUP_LOG_FILE} > /dev/null
            return 1
        fi
    fi
 
    if [ "${BACKUP_USING_TAR}" = "true" ]
    then
        L_PREFIX=`date "+%Y-%m-%d %H:%M:%S"`
 
        if [ "${BACKUP_WORLD_ONLY}" = "true" ]
        then
            echo "${L_PREFIX} [INFO] mc_backup(): Starting a backup of the world of '${INSTANCE}' using tar" | tee -a ${EVENT_LOG_FILE}
            echo "${L_PREFIX} [INFO] mc_backup(): Starting a backup of the world of '${INSTANCE}' using tar" | tee -a ${BACKUP_LOG_FILE} > /dev/null
 
            as_user "cd ${INSTANCE_PATH} && tar --exclude '.git' -czpf ${BACKUP_PATH_TAR}/${BACKUP_PREFIX}_world_${TIMESTAMP_TAR}.tar.gz ${WORLD_NAME} | tee -a ${BACKUP_LOG_FILE} > /dev/null 2>&1"
        else
            echo "${L_PREFIX} [INFO] mc_backup(): Starting a backup of the server '${INSTANCE}' using tar" | tee -a ${EVENT_LOG_FILE}
            echo "${L_PREFIX} [INFO] mc_backup(): Starting a backup of the server '${INSTANCE}' using tar" | tee -a ${BACKUP_LOG_FILE} > /dev/null
 
            as_user "cd `dirname ${INSTANCE_PATH}` && tar --exclude '.git' -czpf ${BACKUP_PATH_TAR}/${BACKUP_PREFIX}_${TIMESTAMP_TAR}.tar.gz `basename ${INSTANCE_PATH}` | tee -a ${BACKUP_LOG_FILE} > /dev/null 2>&1"
        fi
    fi
 
    if [ "${BACKUP_USING_GIT}" = "true" ]
    then
        # Do we have an additional commit message?
        if [ -n "${1}" ]
        then
            MSG=" ${1}"
        else
            MSG=""
        fi
 
        if [ "${2}" = "true" ]
        then
            local GIT_PRM_ALLOW_EMPTY="--allow-empty"
        fi
 
        L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
        L_PREFIX="${L_TIMESTAMP}"
 
        if [ "${BACKUP_WORLD_ONLY}" = "true" ]
        then
            echo "${L_PREFIX} [INFO] mc_backup(): Starting a backup of the world of '${INSTANCE}' using git" | tee -a ${EVENT_LOG_FILE}
            echo "${L_PREFIX} [INFO] mc_backup(): Starting a backup of the world of '${INSTANCE}' using git" | tee -a ${BACKUP_LOG_FILE} > /dev/null
 
            as_user "cd ${WORLD_PATH_REAL} && git add -A . | tee -a ${BACKUP_LOG_FILE} && git commit ${GIT_PRM_ALLOW_EMPTY} -m \"${TIMESTAMP_GIT}${MSG}\" | tee -a ${BACKUP_LOG_FILE}"
        else
            echo "${L_PREFIX} [INFO] mc_backup(): Starting a backup of the server '${INSTANCE}' using git" | tee -a ${EVENT_LOG_FILE}
            echo "${L_PREFIX} [INFO] mc_backup(): Starting a backup of the server '${INSTANCE}' using git" | tee -a ${BACKUP_LOG_FILE} > /dev/null
 
            as_user "cd ${INSTANCE_PATH} && git add -A . | tee -a ${BACKUP_LOG_FILE} && git commit ${GIT_PRM_ALLOW_EMPTY} -m \"${TIMESTAMP_GIT}${MSG}\" | tee -a ${BACKUP_LOG_FILE}"
        fi
    fi
 
    if [ "${BACKUP_USING_RESTIC}" = "true" ]
    then
        L_PREFIX=`date "+%Y-%m-%d %H:%M:%S"`
 
        if [ "${BACKUP_WORLD_ONLY}" = "true" ]
        then
            echo "${L_PREFIX} [INFO] mc_backup(): Starting a backup of the world of '${INSTANCE}' using restic" | tee -a ${EVENT_LOG_FILE}
            echo "${L_PREFIX} [INFO] mc_backup(): Starting a backup of the world of '${INSTANCE}' using restic" | tee -a ${BACKUP_LOG_FILE} > /dev/null
 
            as_user "restic -r ${BACKUP_RESTIC_REPO} backup \"${INSTANCE_PATH}/${WORLD_NAME}\" --verbose --exclude \".git\" | tee -a ${BACKUP_LOG_FILE}"
        else
            echo "${L_PREFIX} [INFO] mc_backup(): Starting a backup of the server '${INSTANCE}' using restic" | tee -a ${EVENT_LOG_FILE}
            echo "${L_PREFIX} [INFO] mc_backup(): Starting a backup of the server '${INSTANCE}' using restic" | tee -a ${BACKUP_LOG_FILE} > /dev/null
 
            as_user "restic -r ${BACKUP_RESTIC_REPO} backup \"${INSTANCE_PATH}\" --verbose --exclude \".git\" | tee -a ${BACKUP_LOG_FILE}"
        fi
    fi
 
    if [ "${BACKUP_SERVICE}" = "true" ]
    then
        L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
        L_PREFIX="${L_TIMESTAMP}"
 
        echo "${L_PREFIX} [INFO] mc_backup(): Backing up service ${SERVICE}" | tee -a ${EVENT_LOG_FILE} > /dev/null
        as_user "cd ${INSTANCE_PATH} && cp -pn ${SERVICE} ${BACKUP_PATH}/${BACKUP_PREFIX}_${TIMESTAMP_TAR}.jar > /dev/null 2>&1"
    fi
 
    L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
    L_PREFIX="${L_TIMESTAMP}"
    echo "${L_PREFIX} [INFO] mc_backup(): Backup of server instance '${INSTANCE}' complete" | tee -a ${EVENT_LOG_FILE} > /dev/null
    echo "${L_PREFIX} [INFO] mc_backup(): Backup of server instance '${INSTANCE}' complete" | tee -a ${BACKUP_LOG_FILE} > /dev/null
}
 
mc_backups_list() {
    if [ "${BACKUP_USING_RESTIC}" = "true" ]
    then
        L_PREFIX=`date "+%Y-%m-%d %H:%M:%S"`
 
        echo "${L_PREFIX} [INFO] mc_backups_list(): Listing latest backups of '${INSTANCE}' made with restic" | tee -a ${EVENT_LOG_FILE}
 
        as_user "restic -r ${BACKUP_RESTIC_REPO} snapshots | grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2}' | cut -d' ' -f1-4 | tail -n 15"
    fi
}
 
mc_backup_wrapper() {
    if [ ${START_TO_DISABLE_AUTOSAVE_DELAY} -ge 0 ]
    then
        mc_say "§dSERVER BACKUP STARTING"
 
        if [ ${SAVEALL_BACKUP_INTERVAL} -ge 0 ]; then
            mc_saveall
            sleep ${SAVEALL_BACKUP_INTERVAL}
        else
            sleep 2
        fi
 
        mc_backup "${1}"
 
        mc_say "§dSERVER BACKUP FINISHED"
    else
        mc_say "§dSERVER BACKUP STARTING, server going read-only"
        mc_saveoff
 
        if [ ${SAVEALL_BACKUP_INTERVAL} -ge 0 ]; then
            mc_saveall
            sleep ${SAVEALL_BACKUP_INTERVAL}
        else
            sleep 5
        fi
 
        mc_backup "${1}"
 
        mc_say "§dSERVER BACKUP FINISHED, server going read-write"
        mc_saveon
    fi
}
 
 
mc_startifcrashed_basic() {
    L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
    L_PREFIX="${L_TIMESTAMP}"
 
    # If the state file is present, then the server is supposed to be running
    if [ -f "${STATE_FILE}" ]
    then
        # If the state file was present, but the process is not found, we assume that the server has crashed
        if ! pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
        then
            echo "${L_PREFIX} [WARNING] mc_startifcrashed_basic(): ${SERVICE} is not running (crashed?)" | tee -a ${EVENT_LOG_FILE}
            echo "${L_PREFIX} [INFO] mc_startifcrashed_basic(): Attempting to start ${SERVICE}..." | tee -a ${EVENT_LOG_FILE}
 
            mc_start
 
            L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
            L_PREFIX="${L_TIMESTAMP}"
 
            if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
            then
                echo "${L_PREFIX} [INFO] mc_startifcrashed_basic(): ${SERVICE} is now running" | tee -a ${EVENT_LOG_FILE}
            else
                echo "${L_PREFIX} [ERROR] mc_startifcrashed_basic(): Could not start ${SERVICE}" | tee -a ${EVENT_LOG_FILE}
            fi
        else
            echo "${L_PREFIX} [INFO] mc_startifcrashed_basic(): ${SERVICE} is running" | tee -a ${EVENT_LOG_FILE}
        fi
    else
        echo "${L_PREFIX} [INFO] mc_startifcrashed_basic(): ${SERVICE} has been stopped gracefully" | tee -a ${EVENT_LOG_FILE}
    fi
}
 
 
mc_startifcrashed_ping() {
    L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
    L_PREFIX="${L_TIMESTAMP}"
 
    # If the state file is present, then the server is supposed to be running
    if [ -f "${STATE_FILE}" ]
    then
        # If the state file was present, and the process is found, we try to ping the server
        if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
        then
            echo "${L_PREFIX} [INFO] mc_startifcrashed_ping(): ${SERVICE} is running, pinging it..." | tee -a ${EVENT_LOG_FILE}
 
            # We try the ping a maximum of PING_RETRY_COUNT times, to try and avoid false positive failures and restarts
            COUNTER=0
            while [ ${COUNTER} -lt ${PING_RETRY_COUNT} ]; do
 
                if ${PING_INVOCATION} | grep ': OK' > /dev/null
                then
                    L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
                    L_PREFIX="${L_TIMESTAMP}"
 
                    echo "${L_PREFIX} [INFO] mc_startifcrashed_ping(): ${SERVICE} responded to ping" | tee -a ${EVENT_LOG_FILE}
                    break
                fi
 
                sleep ${PING_RETRY_DELAY}
            done
 
            # If the ping failed every time, then we assume that the server has crashed and we will kill it and start it up again
            if [ ${COUNTER} -ge ${PING_RETRY_COUNT} ]
            then
                L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
                L_PREFIX="${L_TIMESTAMP}"
 
                echo "${L_PREFIX} [WARNING] mc_startifcrashed_ping(): ${SERVICE} doesn't respond to ping (crashed?)" | tee -a ${EVENT_LOG_FILE}
                echo "${L_PREFIX} [INFO] mc_startifcrashed_ping(): Killing and (re-)starting ${SERVICE}" | tee -a ${EVENT_LOG_FILE}
 
                mc_kill
                sleep ${KILL_TO_START_DELAY}
                mc_start
 
                L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
                L_PREFIX="${L_TIMESTAMP}"
 
                if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
                then
                    echo "${L_PREFIX} [INFO] mc_startifcrashed_ping(): ${SERVICE} is now running" | tee -a ${EVENT_LOG_FILE}
                else
                    echo "${L_PREFIX} [ERROR] mc_startifcrashed_ping(): Could not start ${SERVICE}" | tee -a ${EVENT_LOG_FILE}
                fi
            fi
        else
            # Process not found (crashed?), we try to start the server
            echo "${L_PREFIX} [WARNING] mc_startifcrashed_ping(): ${SERVICE} not running (crashed?)" | tee -a ${EVENT_LOG_FILE}
            echo "${L_PREFIX} [INFO] mc_startifcrashed_ping(): Attempting to start ${SERVICE}" | tee -a ${EVENT_LOG_FILE}
 
            mc_start
 
            L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
            L_PREFIX="${L_TIMESTAMP}"
 
            if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
            then
                echo "${L_PREFIX} [INFO] mc_startifcrashed_ping(): ${SERVICE} is now running" | tee -a ${EVENT_LOG_FILE}
            else
                echo "${L_PREFIX} [ERROR] mc_startifcrashed_ping(): Could not start ${SERVICE}" | tee -a ${EVENT_LOG_FILE}
            fi
        fi
    else
        # No state file present, the server is supposed to be down
        echo "${L_PREFIX} [INFO] mc_check(): ${SERVICE} has been stopped gracefully" | tee -a ${EVENT_LOG_FILE}
    fi
}
 
 
mc_kill() {
    L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
    L_PREFIX="${L_TIMESTAMP}"
 
    if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
    then
        echo "${L_PREFIX} [INFO] mc_kill(): Killing minecraft server instance '${INSTANCE}'..." | tee -a ${EVENT_LOG_FILE}
 
        as_user "pkill -SIGKILL -u ${USERNAME} -f ${SERVICE}"
        sleep ${POST_KILL_DELAY}
 
        COUNTER=0
        while [ ${COUNTER} -lt ${KILL_GRACE_DELAY} ]; do
            if ! pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
            then
                L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
                L_PREFIX="${L_TIMESTAMP}"
                echo "${L_PREFIX} [INFO] mc_kill(): Server instance '${INSTANCE}' has been killed" | tee -a ${EVENT_LOG_FILE}
 
                # FIXME: Could this be done cleaner?
                screen -wipe
 
                if [ "${USE_TEMP_LOCATION}" = "true" ]
                then
                    # Copy the save files from the temp directory (in RAM) into the actual server directory
                    copy_save_files_from_tmp_to_game_dir
                    local RET=$?
 
                    if [ $RET -eq 0 ]; then
                        remove_save_files_from_tmp_location
                    fi
                fi
 
                break
            fi
 
            sleep 1
 
            ((COUNTER += 1))
        done
 
        if [ ${COUNTER} -ge ${KILL_GRACE_DELAY} ]
        then
            echo "${L_PREFIX} [ERROR] mc_kill(): Unable to kill minecraft server '${INSTANCE}'" | tee -a ${EVENT_LOG_FILE}
        fi
    else
        echo "${L_PREFIX} [WARNING] mc_kill(): Minecraft server instance '${INSTANCE}' was not running" | tee -a ${EVENT_LOG_FILE}
    fi
}
 
 
mc_download_server() {
    # Only do something if we have a version argument
    if [ -n "${1}" ]
    then
        VERSION="${1}"
        # If the requested server version doesn't yet exist, we attempt to download it
        if [ ! -f "${SERVER_FILES_PATH}/${SERVER_FILE_PREFIX}${VERSION}.jar" ]
        then
            MC_SERVER_URL="https://s3.amazonaws.com/Minecraft.Download/versions/${VERSION}/minecraft_server.${VERSION}.jar"
            as_user "wget -q -O \"${SERVER_FILES_PATH}/${SERVER_FILE_PREFIX}${VERSION}.jar\" ${MC_SERVER_URL}"
 
            # If wget returns 0
            if [ "$?" -eq "0" ]
            then
                L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
                L_PREFIX="${L_TIMESTAMP}"
                echo "${L_PREFIX} [INFO] mc_download_server(): Downloaded ${MC_SERVER_URL} to ${SERVER_FILES_PATH}/${SERVER_FILE_PREFIX}${VERSION}.jar" | tee -a ${EVENT_LOG_FILE}
            else
                # Download failed
                echo "${L_PREFIX} [ERROR] mc_download_server(): Download of ${MC_SERVER_URL} failed" | tee -a ${EVENT_LOG_FILE}
                # Remove the empty file just created
                as_user "rm ${SERVER_FILES_PATH}/${SERVER_FILE_PREFIX}${VERSION}.jar"
                exit 1
            fi
        fi
    fi
}
 
 
mc_update() {
    CURRENT_VERSION=`readlink -f "${INSTANCE_PATH}/${SERVICE}" | sed "s/.*\/${SERVER_FILE_PREFIX}\(.*\)\.jar/\1/"`
 
    # Any version change via this script on this server instance is forbidden
    if [ "${ALLOW_UPDATES}" = 'false' ] && [ "${ALLOW_DOWNGRADES}" = 'false' ]
    then
        L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
        L_PREFIX="${L_TIMESTAMP}"
        echo "${L_PREFIX} [ERROR] mc_update(): Any updates or downgrades of '${SERVICE}' are not allowed (@ ${CURRENT_VERSION})" | tee -a ${EVENT_LOG_FILE}
        return
    fi
 
    if [ -z "${1}" ]
    then
        # No version specified, assume we want the latest stable release
        VERSIONS_URL="https://launchermeta.mojang.com/mc/game/version_manifest.json"
        # Old URL: VERSIONS_URL="https://s3.amazonaws.com/Minecraft.Download/versions/versions.json"
 
        as_user "wget -q -O ${VERSIONS_JSON} ${VERSIONS_URL}"
 
        # Get the latest[release] value
        VERSION=`tr '\r\n' ' ' < ${VERSIONS_JSON} | sed "s/ //g" | sed 's/.*\("latest[^}]\+}\).*/\1/' | sed 's/.*"release":"\([^"]\+\)"}/\1/'`
    else    # Use the version given as an argument
        VERSION="${1}"
    fi
 
    echo "Target version: ${VERSION}, Current version: ${CURRENT_VERSION}"
    #exit
 
    # If the requested version is different from the current version
    if [ "${CURRENT_VERSION}" != "${VERSION}" ]
    then
        # Check that the requested version change is permitted
        # FIXME This won't work correctly with alpha, beta etc. prefixed versions
        if [[ "${VERSION}" < "${CURRENT_VERSION}" ]] && [ "${ALLOW_DOWNGRADES}" != 'true' ]
        then
            L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
            L_PREFIX="${L_TIMESTAMP}"
            echo "${L_PREFIX} [ERROR] mc_update(): Downgrades of '${SERVICE}' are not allowed (${CURRENT_VERSION} -> ${VERSION})" | tee -a ${EVENT_LOG_FILE}
            return
        fi
        # FIXME This won't work correctly with alpha, beta etc. prefixed versions
        if [[ "${VERSION}" > "${CURRENT_VERSION}" ]] && [ "${ALLOW_UPDATES}" != 'true' ]
        then
            L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
            L_PREFIX="${L_TIMESTAMP}"
            echo "${L_PREFIX} [ERROR] mc_update(): Updates of '${SERVICE}' are not allowed (${CURRENT_VERSION} -> ${VERSION})" | tee -a ${EVENT_LOG_FILE}
            return
        fi
 
        # If the server is currently running, broadcast a message before starting the update process
        if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
        then
            RUNNING="true"
 
            L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
            L_PREFIX="${L_TIMESTAMP}"
            echo "${L_PREFIX} [INFO] mc_update(): ${SERVICE} is running, stopping it and starting the update" | tee -a ${EVENT_LOG_FILE}
 
            mc_say "§d=== SERVER UPDATE STARTING ==="
            sleep 5
            mc_stop "broadcast"
        else
            RUNNING="false"
 
            L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
            L_PREFIX="${L_TIMESTAMP}"
            echo "${L_PREFIX} [INFO] mc_update(): ${SERVICE} is stopped, starting the update" | tee -a ${EVENT_LOG_FILE}
        fi
 
        mc_backup "Backup before updating to version ${VERSION} (@ ${CURRENT_VERSION})" "true"
        mc_download_server ${VERSION}
 
        # If the requested server file exists, update the symlink
        if [ -f "${SERVER_FILES_PATH}/${SERVER_FILE_PREFIX}${VERSION}.jar" ]
        then
            as_user "ln -fs \"${SERVER_FILES_PATH}/${SERVER_FILE_PREFIX}${VERSION}.jar\" \"${INSTANCE_PATH}/${SERVICE}\""
 
            if [ "${RUNNING}" = "true" ]
            then
                L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
                L_PREFIX="${L_TIMESTAMP}"
                echo "${L_PREFIX} [INFO] mc_update(): Updated '${SERVICE}' to version '${VERSION}', starting ${SERVICE}..." | tee -a ${EVENT_LOG_FILE}
 
                mc_start
            else
                L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
                L_PREFIX="${L_TIMESTAMP}"
                echo "${L_PREFIX} [INFO] mc_update(): Updated '${SERVICE}' to version '${VERSION}'" | tee -a ${EVENT_LOG_FILE}
            fi
        else
            # Download failed
            L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
            L_PREFIX="${L_TIMESTAMP}"
            echo "${L_PREFIX} [ERROR] mc_update(): Update of '${SERVICE}' to version '${VERSION}' failed" | tee -a ${EVENT_LOG_FILE}
        fi
    else
        L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
        L_PREFIX="${L_TIMESTAMP}"
        echo "${L_PREFIX} [WARNING] mc_update(): '${SERVICE}' is already at version '${VERSION}', not doing anything" | tee -a ${EVENT_LOG_FILE}
    fi
}
 
 
mc_say() {
    L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
    L_PREFIX="${L_TIMESTAMP}"
 
    if [ -n "${1}" ]
    then
        MSG="${1}"
 
        if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
        then
#           echo "${L_PREFIX} [INFO] mc_say(): ${SERVICE} is running, saying '${MSG}'" | tee -a ${EVENT_LOG_FILE}
            as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"say ${MSG}\"\015'"
#       else
#           echo "${L_PREFIX} [WARNING] mc_say(): ${SERVICE} is not running" | tee -a ${EVENT_LOG_FILE}
        fi
    else
        echo "${L_PREFIX} [ERROR] mc_say(): You must specify a message" | tee -a ${EVENT_LOG_FILE}
    fi
}
 
 
mc_command() {
    L_TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
    L_PREFIX="${L_TIMESTAMP}"
 
    if [ "${1}" ]
    then
        command="${1}"
 
        if pgrep -u ${USERNAME} -f ${SERVICE} > /dev/null
        then
            echo "${L_PREFIX} [INFO] mc_command(): ${SERVICE} is running, executing command '${command}'" | tee -a ${EVENT_LOG_FILE}
            as_user "screen -p 0 -S ${SCREEN_SESSION} -X eval 'stuff \"${command}\"\015'"
        fi
    else
        echo "${L_PREFIX} [ERROR] mc_command(): You must specify a server command" | tee -a ${EVENT_LOG_FILE}
    fi
}

Comments