diff --git a/minecraft b/minecraft deleted file mode 100755 index 2d743e9..0000000 --- a/minecraft +++ /dev/null @@ -1,659 +0,0 @@ -#!/bin/bash - -### BEGIN INIT INFO -# Provides: minecraft -# Required-Start: $local_fs $remote_fs -# Required-Stop: $local_fs $remote_fs -# Should-Start: $network -# Should-Stop: $network -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Minecraft server -# Description: Init script for minecraft/bukkit server, with rolling logs and use of ramdisk for less lag. -### END INIT INFO - -# Minecraft/Bukkit init script by Marcus Whybrow -# - Modified from a script created by Ahtenus (https://github.com/Ahtenus/minecraft-init) -# - Which was apparently based upon http://www.minecraftwiki.net/wiki/Server_startup_script - -# The location of the configuration file for this script -CONFIG="/opt/minecraft/server1/manager.config" - - -### Load configuration variables -source $CONFIG - - -### General Utility functions - -# Returns the current time as a UNIX timestamp (in seconds since 1970) -now() { - date +%s -} - -# This function is used to quite the stdout of another function -# like this: quite $(other_func) -quite() { - return $(true) -} - -as_user() { - if [ $(whoami) == $SERVER_USER ] ; then - bash -c "$1" - else - su - $SERVER_USER -s /bin/bash -c "$1" - fi -} - - -### Log Utility Functions - -# Gets the time UNIX timestamp for a server log line -# $1: A server log line -# returns: Time in seconds since 1970-01-01 00:00:00 UTC -log_line_get_time() { - time_string=$(echo $1 | awk '{print $1 " " $2}') - date -d "$time_string" "+%s" 2> /dev/null -} - -# Watches the log -# $1: The line in the log to wait for -# $2: A UNIX timestamp (seconds since 1970) which the $1 line must be after -# returns: When the line is found -log_wait_for_line() { - # Make sure there is a server log to check - as_user "touch $SERVER_LOG" - - regex="^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} \[.*\] ${1}" - - while read LINE - do - time=$(log_line_get_time "$LINE") - - # If the entry is old enough and matches the regular expression - if [[ $time -ge $2 && $LINE =~ $regex ]] - then - echo $LINE - break - fi - done < <(as_user "tail --follow --lines=100 --sleep-interval=0.1 $SERVER_LOG") -} - - -### Server Utility Functions - -server_is_running() { - if ps ax | grep -v grep | grep "$SCREEN_NAME $INVOCATION" > /dev/null - then - return $(true) - else - return $(false) - fi -} - -# Gets the process ID for the server if running, otherwise it outputs nothing -server_pid() { - ps ax | grep -v grep | grep "$SCREEN_NAME $INVOCATION" | awk '{print $1}' -} - -server_wait_for_stop() { - pid=$(server_pid) - - while ps -p $pid > /dev/null - do - sleep 0.1 - done -} - -# $1: A line of text to enter into the server console -server_eval() { - as_user "screen -p 0 -S $SCREEN_NAME -X eval 'stuff \"$1\"\015'" -} - -# $1: A line of text to enter into the server console -# $2: The line of text in the log to wait for -server_eval_and_wait() { - time=$(now) - server_eval $1 - log_wait_for_line "$2" "$time" -} - - -### World Handling Functions - -worlds_get() { - a=1 - for NAME in $(ls ${WORLD_STORAGE_PATH}) - do - if [ -d ${WORLD_STORAGE_PATH}/$NAME ] - then - WORLDNAME[$a]=$NAME - if [ -e ${WORLD_STORAGE_PATH}/$NAME/ramdisk ] - then - WORLDRAM[$a]=true - else - WORLDRAM[$a]=false - fi - a=$a+1 - fi - done -} - -# Creates symbolic links in the server directory (SERVER_PATH) for each -# of the Minecraft worlds located in the world storage directory (WORD_STORAGE_PATH). -worlds_ensure_links() { - echo "Updating world symbolic links..." - - worlds_get - for INDEX in ${!WORLDNAME[@]} - do - # -L checks for the path being a link rather than a file - # ! -a, since it is within double square brackets means: the negation of - # the existence of the file. In other words: true if does not exist - if [[ -L ${SERVER_PATH}/${WORLDNAME[$INDEX]} || ! -a ${SERVER_PATH}/${WORLDNAME[$INDEX]} ]] - then - # If there is a symbolic link in the SERVER_PATH to this world or there is not - # a directory in the SERVER_PATH for this world. - - # Get the original file path the symbolic link is pointing to - # If there is no link, link_target will contain nothing - link_target=$(readlink ${SERVER_PATH}/${WORLDNAME[$INDEX]}) - - if ${WORLDRAM[$INDEX]} - then - # If this world is marked as loaded into RAM - - if [ "${link_target}" != "${RAMDISK_PATH}/${WORLDNAME[$INDEX]}" ] - then - # If the symbolic link does not point to the RAM version of the world - - # Remove the symbolic link if it exists - as_user "rm -f ${SERVER_PATH}/${WORLDNAME[$INDEX]}" - - # Create a new symbolic link pointing to the RAM version of the world - as_user "ln -s ${RAMDISK_PATH}/${WORLDNAME[$INDEX]} ${SERVER_PATH}/${WORLDNAME[$INDEX]}" - echo "Created a link for ${WORLDNAME[$INDEX]} which is in RAM: ${RAMDISK_PATH}/${WORLDNAME[$INDEX]}" - fi - else - # Otherwise the world is not loaded into RAM, and is just on disk - - if [ "${link_target}" != "${WORLD_STORAGE_PATH}/${WORLDNAME[$INDEX]}" ] - then - # If the symbolic link does not point to the disk version of the world - - # Remove the symbolic link if it exists - as_user "rm -f ${SERVER_PATH}/${WORLDNAME[$INDEX]}" - - # Create a new symbolic link pointing to the disk version of the world - as_user "ln -s ${WORLD_STORAGE_PATH}/${WORLDNAME[$INDEX]} ${SERVER_PATH}/${WORLDNAME[$INDEX]}" - - echo "Created a link for ${WORLDNAME[$INDEX]} which on disk: ${WORLD_STORAGE_PATH}/${WORLDNAME[$INDEX]}" - fi - fi - else - # There was no symbolic link, and there was a directory, meaning a world - # directory has been placed in SERVER_PATH, this is not allowed: - echo "Could not process ${WORLDNAME[$INDEX]}. please move all worlds to ${WORLD_STORAGE_PATH}." - exit 1 - fi - done - echo "Finished updating world symbolic links." -} - -world_to_ram() { - as_user "mkdir -p ${RAMDISK_PATH}/$1 && rsync -rt --exclude 'ramdisk' ${WORLD_STORAGE_PATH}/$1/ ${RAMDISK_PATH}/$1" -} - -worlds_to_ram() { - echo "Synchronising worlds to RAM..." - - worlds_get - for INDEX in ${!WORLDNAME[@]} - do - if ${WORLDRAM[$INDEX]} - then - if [ -L ${SERVER_PATH}/${WORLDNAME[$INDEX]} ] - then - printf "[RAM] \"${WORLDNAME[$INDEX]}\": Synchronising to RAM... " - world_to_ram "${WORLDNAME[$INDEX]}" - echo "Done." - fi - else - echo "[DSK] \"${WORLDNAME[$INDEX]}\": Nothing to do." - fi - done - - echo "Finished synchronising worlds to RAM." -} - -worlds_to_disk() { - echo "Synchronising worlds in RAM to disk..." - - worlds_get - for INDEX in ${!WORLDNAME[@]} - do - if [ -e ${RAMDISK_PATH}/${WORLDNAME[$INDEX]} ] - then - printf "[RAM] \"${WORLDNAME[$INDEX]}\": Synchronising to disk... " - as_user "rsync -rt --exclude 'ramdisk' ${RAMDISK_PATH}/${WORLDNAME[$INDEX]}/ ${WORLD_STORAGE_PATH}/${WORLDNAME[$INDEX]}" - echo "Done." - else - echo "[DSK] \"${WORLDNAME[$INDEX]}\": Nothing to do." - fi - done - - echo "Finished synchronising worlds in RAM to disk." -} - -world_toggle_ramdisk_state() { - if [ ! -e ${WORLD_STORAGE_PATH}/$1 ] - then - echo "World \"$1\" not found." - exit 1 - fi - - if [ -e ${WORLD_STORAGE_PATH}/$1/ramdisk ] - then - as_user "rm ${WORLD_STORAGE_PATH}/$1/ramdisk" - as_user "rm -r ${RAMDISK_PATH}/$1" - echo "Removed the RAM flag from \"$1\", and deleted it from RAM." - else - as_user "touch ${WORLD_STORAGE_PATH}/$1/ramdisk" - echo "Added the RAM flag to \"$1\"." - printf "Copying world to RAM... " - quite $(world_to_ram "$1") - echo "Done." - fi - echo "Changes will only take effect after server is restarted." -} - - -### Server Control Functions - -server_start() { - if server_is_running - then - echo "$JAR is already running!" - else - worlds_ensure_links - worlds_to_ram - - time=$(now) - - printf "Starting server... " - as_user "cd $SERVER_PATH && screen -dmS $SCREEN_NAME $INVOCATION" - quite $(log_wait_for_line "$CONFIRMATIONS_START" "$time") - echo "Done." - fi -} - -server_saveall() { - if server_is_running - then - # Send the "save-all" command and wait for it to finish - printf "Forcing save... " - quite $(server_eval_and_wait "save-all" "$CONFIRMATIONS_SAVE_ALL") - echo "Done." - else - echo "$JAR was not running. Not forcing save." - fi -} - -server_saveoff() { - if server_is_running - then - # Send the "save-off" command and wait for it to finish - printf "Disabling level saving... " - quite $(server_eval_and_wait "save-off" "$CONFIRMATIONS_SAVE_OFF") - echo "Done." - - # Also save all - server_saveall - - # Not sure what this does, might be important - sync - else - echo "$JAR was not running. Not suspending saves." - fi -} - -server_saveon() { - if server_is_running - then - # Send the "save-on" command and wait for it to finish - printf "Enabling level saving... " - quite $(server_eval_and_wait "save-on" "$CONFIRMATIONS_SAVE_ON") - echo "Done." - else - echo "$JAR was not running. Not resuming saves." - fi -} - -server_stop() { - if server_is_running - then - server_saveall - - printf "Stopping the server... " - server_eval "stop" - - server_wait_for_stop - echo "Done." - else - echo "$JAR was not running." - fi -} - -server_restart() { - # Restarts the server if it is already running - if server_is_running - then - # Stop the server - server_stop - - # Synchronise all worlds in RAM to disk - worlds_to_disk - # Ensure world symbolic links are up to date - worlds_ensure_links - # Synchronise worlds back to RAM - worlds_to_ram - - # Start the server again - server_start - else - echo "$JAR is not running. Only running servers may be restarted." - fi -} - -# Not really tested this -server_update_jars() { - if server_is_running - then - echo "$JAR is running! Will not start update." - else - # Update minecraft_server.jar - echo "Updating minecraft_server.jar...." - MC_SERVER_URL=http://minecraft.net/$(wget -q -O - http://www.minecraft.net/download.jsp | grep minecraft_server.jar\ | cut -d \" -f 2) - as_user "cd ${SERVER_PATH} && wget -q -O ${SERVER_PATH}/minecraft_server.jar.update $MC_SERVER_URL" - if [ -f ${SERVER_PATH}/minecraft_server.jar.update ] - then - if $(diff ${SERVER_PATH}/minecraft_server.jar ${SERVER_PATH}/minecraft_server.jar.update >/dev/null) - then - echo "You are already running the latest version of the Minecraft server." - as_user "rm ${SERVER_PATH}/minecraft_server.jar.update" - else - as_user "mv ${SERVER_PATH}/minecraft_server.jar.update $MCPATH/minecraft_server.jar" - echo "Minecraft successfully updated." - fi - else - echo "Minecraft update could not be downloaded." - fi - - # Update craftbukkit - - echo "Updating craftbukkit...." - as_user "cd ${SERVER_PATH} && wget -q -O ${SERVER_PATH}/craftbukkit.jar.update http://dl.bukkit.org/latest-rb/craftbukkit.jar" - if [ -f ${SERVER_PATH}/craftbukkit.jar.update ] - then - if $(diff ${SERVER_PATH}/craftbukkit-0.0.1-SNAPSHOT.jar $MCPATH/craftbukkit.jar.update > /dev/null) - then - echo "You are already running the latest version of CraftBukkit." - as_user "rm ${SERVER_PATH}/craftbukkit.jar.update" - else - as_user "mv ${SERVER_PATH}/craftbukkit.jar.update $MCPATH/craftbukkit-0.0.1-SNAPSHOT.jar" - echo "CraftBukkit successfully updated." - fi - else - echo "CraftBukkit update could not be downloaded." - fi - fi -} - - -### Backup Functions - -backup_server() { - path=${COMPLETE_BACKUP_PATH}/$(date "+%Y-%m-%d-%H-%M-%S").zip - as_user "mkdir -p $COMPLETE_BACKUP_PATH" - - zip_flags="-rq" - - # Add the "y" flag if symbolic links should not be followed - if [ "$COMPLETE_BACKUP_FOLLOW_SYMLINKS" != "true" ] - then - zip_flags="${zip_flags}y" - fi - - # Zip up the server directory - printf "Backing up the entire server directory... " - as_user "mkdir -p ${COMPLETE_BACKUP_PATH} && cd ${SERVER_PATH} && zip ${zip_flags} $path ." - echo "Done." -} - -backup_worlds() { - worlds_get - echo "Backing up worlds..." - for INDEX in ${!WORLDNAME[@]} - do - printf "Backing up world \"${WORLDNAME[$INDEX]}\"... " - - dir="${WORLD_SNAPSHOT_PATH}/${WORLDNAME[$INDEX]}" - file_name="$(date "+%Y-%m-%d-%H-%M-%S").zip" - as_user "mkdir -p ${dir} && cd ${WORLD_STORAGE_PATH}/${WORLDNAME[$INDEX]} && zip -rq ${dir}/${file_name} ." - - echo "Done." - done - echo "Finished backing up worlds." -} - -# An experimental function which backs up config files for all -# Bukkit plugins. Only recognises .yml files currently -# I use the backup_server function instead to get everything -# for sure. -backup_configs() { - dir=${CONFIG_BACKUP_PATH} - file_name="$(date "+%Y-%m-%d-%H-%M-%S").zip" - - printf "Backing up plugin config files... " - as_user "mkdir -p ${dir} && cd ${SERVER_PLUGIN_PATH} && zip -Rq ${dir}/${file_name} '${CONFIG_BACKUP_PATTERN}'" - echo "Done." -} - - -### Maintenance Functions - -log_roll() { - # Moves and Gzips the logfile, a big log file slows down the - # server A LOT (what was notch thinking?) - - path=${LOG_ARCHIVE_PATH}/${SERVER_NAME}-$(date +%F-%H-%M-%S).log - - printf "Rolling server logs... " - as_user "mkdir -p $LOG_ARCHIVE_PATH && cp $SERVER_LOG $path && gzip $path" - - if [ $? -eq 0 ] - then - as_user "cp /dev/null $SERVER_LOG && echo \"Previous logs rolled to $path\" > $SERVER_LOG" - else - echo "Failed to rotate logs to $path.gz" - fi - - echo "Done." -} - - -### Script switch statement - -case "$1" in - start) - # Starts the server - server_start - ;; - stop) - # Stops the server - - if server_is_running - then - if [[ $2 != "now" ]] - then - server_eval "say ${MESSAGE_SERVER_STOP_WARNING}" - - echo "Issued the warning \"${MESSAGE_SERVER_STOP_WARNING}\" to players." - echo "Shutting down in ${CONFIG_SERVER_STOP_DELAY} seconds..." - - sleep ${CONFIG_SERVER_STOP_DELAY} - fi - - server_stop - worlds_to_disk - else - echo "$JAR was not running." - fi - ;; - restart) - if server_is_running - then - if [[ $2 != "now" ]] - then - server_eval "say ${MESSAGE_SERVER_RESTART_WARNING}" - - echo "Issued the warning \"${MESSAGE_SERVER_RESTART_WARNING}\" to players." - echo "Restarting in ${CONFIG_SERVER_RESTART_DELAY} seconds..." - - sleep ${CONFIG_SERVER_RESTART_DELAY} - fi - - server_restart - else - echo "$JAR was not running. Cannot restart a stopped server. Try \"start\" instead." - fi - ;; - backup) - # Backs up worlds - - if server_is_running - then - server_eval "say ${MESSAGE_SERVER_WORLDS_BACKUP_STARTED}" - server_saveoff - worlds_to_disk - - backup_worlds - - server_saveon - server_eval "say ${MESSAGE_SERVER_WORLDS_BACKUP_FINISHED}" - else - backup_worlds - fi - ;; - complete-backup) - # Backup everything - if server_is_running - then - server_eval "say ${MESSAGE_SERVER_COMPLETE_BACKUP_STARTED}" - server_saveoff - - backup_server - - server_saveon - server_eval "say ${MESSAGE_SERVER_COMPLETE_BACKUP_FINISHED}" - fi - ;; - update) - echo "Not supported yet." - # Update minecraft_server.jar and craftbukkit.jar (thanks karrth) - #server_eval "say SERVER UPDATE IN 10 SECONDS." - #server_stop - #worlds_to_disk - #backup_server - #server_update_jars - #check_links - #server_start - ;; - to-disk) - # Writes from the ramdisk to disk, in case the server crashes. - # Using ramdisk speeds things up a lot, especially if you allow - # teleportation on the server. - server_saveoff - worlds_to_disk - server_saveon - ;; - connected) - # Lists connected users - - # Send the list command to the server, and wait for the response - server_eval_and_wait "list" "Connected players:" - ;; - log-roll) - log_roll - ;; - last) - echo "Not yet supported." - # greps for recently logged in users - #echo Recently logged in users: - #cat $SERVER_LOG | awk '/entity|conn/ {sub(/lost/,"disconnected");print $1,$2,$4,$5}' - ;; - status) - # Shows server status - if server_is_running - then - echo "$JAR is running." - else - echo "$JAR is not running." - fi - ;; - version) - echo "Not supported yet." - ;; - links) - worlds_ensure_links - ;; - ramdisk) - world_toggle_ramdisk_state $2 - ;; - worlds) - worlds_get - for INDEX in ${!WORLDNAME[@]} - do - if ${WORLDRAM[$INDEX]} - then - echo "[RAM] ${WORLDNAME[$INDEX]}" - else - echo "[DSK] ${WORLDNAME[$INDEX]}" - fi - done - ;; - console) - # This only works if the terminal invoking this script - # is logged in as the user $USER_NAME, this is a security - # measure enforced by screen. - as_user "screen -r ${SCREEN_NAME}" - ;; - help) - echo "Usage: $0 command" - echo - echo "start - Starts the server" - echo "stop - stops the server gracefully, after warning players" - echo "stop now - stops the server gracefully, right now!" - echo "restart - restarts the server gracefully, after warning players" - echo "restart now - restarts the server gracefully, right now!" - echo "console - opens the screen process (Press Ctr+A then D to exit)" - echo "backup - backs up worlds in \"world storage\"" - echo "complete-backup - backups the entire server folder" - echo "log-roll - Moves and gzips the logfile" - echo "to-disk - copies any worlds in RAM to disk" - echo "connected - lists connected users" - echo "status - Shows server status" - echo "links - creates nessesary symlinks" - echo "worlds - shows a list of available worlds" - echo "ramdisk WORLD - toggles ramdisk configuration for WORLD" - echo "update - Not yet supported" - echo "version - Not yet supported" - echo "last - Not yet supported" - ;; - *) - echo "No such command see $0 help" - exit 1 - ;; -esac - -exit 0 \ No newline at end of file