From 1b874838cfbc56c935da8ec3537d18d3bc2f15cf Mon Sep 17 00:00:00 2001 From: Marcus Whybrow Date: Fri, 13 Jul 2012 19:56:57 +0100 Subject: [PATCH] Refactored setting registration. Allows for default values. Added `msm config` command. Settings are now registered using the register_setting and register_server_setting functions. Settings registered via the first function can be overridden in /etc/msm.conf, and settings registered via the second function may also be overridden in server.properties. Additionally, global variables are now better protected from confusion with stronger namespacing. Several settings have changed there names, these can be seen in the diff for `msm.conf`. The same name changes also take effect in all `server.properties files. `msm config` now displays a list of all setting when arguments are omitted. `msm config` is a new command which lists all setting values. --- bash_completion/msm | 2 +- init/msm | 715 ++++++++++++++++++++++---------------------- msm.conf | 37 +-- 3 files changed, 375 insertions(+), 379 deletions(-) diff --git a/bash_completion/msm b/bash_completion/msm index 123da35..42f15df 100644 --- a/bash_completion/msm +++ b/bash_completion/msm @@ -74,7 +74,7 @@ _msm() { if [ -d "$SERVER_STORAGE_PATH" ]; then local servers="$(ls -1 "$SERVER_STORAGE_PATH")" fi - options="help start stop restart version server jargroup all $servers" + options="help start stop restart version server jargroup all config $servers" else case "${COMP_WORDS[1]}" in stop|restart) diff --git a/init/msm b/init/msm index 84e673e..c4c2025 100755 --- a/init/msm +++ b/init/msm @@ -30,12 +30,6 @@ VERSION="0.5.2" ### Config variables the user should not need/want to change -# Jar group file which contains the download target URL -declare -r JARGROUP_TARGET="target.txt" -# Jar group directory name to download new jars to, is deleted afterwards -declare -r JARGROUP_DOWNLOAD_DIR="downloads" -# The server configuration file name -declare -r SERVER_CONF_NAME="server.properties" # The start of a regex to find a log line declare -r LOG_REGEX="^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} \[.*\]" @@ -48,6 +42,11 @@ declare STOP_COUNTDOWN # "true" whilst the script is counting down a delay to restart the server declare RESTART_COUNTDOWN +# Variables used for registration +COMMAND_COUNT=0 +SETTING_COUNT=0 +SERVER_SETTING_COUNT=0 + ### Utility Functions @@ -114,11 +113,11 @@ debug() { # $1: The name to check is_valid_name() { local valid="^[a-zA-Z0-9\_\-]+$" - local invalid="^(start|stop|restart|version|server|jargroup|all)$" + local invalid="^(start|stop|restart|version|server|jargroup|all|config)$" if [[ "$1" =~ $valid ]]; then if [[ "$1" =~ $invalid ]]; then - error_exit INVALID_ARGUMENT "Invalid name \"$1\": A name may not be any of the following reserved worlds \"start\", \"stop\", \"restart\", \"server\", \"version\", \"jargroup\" or \"all\"." + error_exit INVALID_ARGUMENT "Invalid name \"$1\": A name may not be any of the following reserved worlds \"start\", \"stop\", \"restart\", \"server\", \"version\", \"jargroup\", \"all\" or \"config\"." else return 0 fi @@ -173,15 +172,15 @@ log_line_get_time() { # Moves a world to RAM # $1: the ID of the world to move world_to_ram() { - if [ ! -z "$RAMDISK_STORAGE_PATH" ]; then - as_user "${SERVER_USER_NAME[${WORLD_SERVER_ID[$1]}]}" "mkdir -p \"${WORLD_RAMDISK_PATH[$1]}\" && rsync -rt --exclude '$(basename "${WORLD_FLAG_INRAM[$1]}")' \"${WORLD_PATH[$1]}/\" \"${WORLD_RAMDISK_PATH[$1]}\"" + if [ ! -z "$SETTINGS_RAMDISK_STORAGE_PATH" ]; then + as_user "${SERVER_USERNAME[${WORLD_SERVER_ID[$1]}]}" "mkdir -p \"${WORLD_RAMDISK_PATH[$1]}\" && rsync -rt --exclude '$(basename "${WORLD_FLAG_INRAM[$1]}")' \"${WORLD_PATH[$1]}/\" \"${WORLD_RAMDISK_PATH[$1]}\"" fi } # Moves a world in RAM to disk # $1: the ID of the world to move world_to_disk() { - as_user "${SERVER_USER_NAME[${WORLD_SERVER_ID[$1]}]}" "rsync -rt --exclude '$(basename "${WORLD_FLAG_INRAM[$1]}")' \"${WORLD_RAMDISK_PATH[$1]}/\" \"${WORLD_PATH[$1]}\"" + as_user "${SERVER_USERNAME[${WORLD_SERVER_ID[$1]}]}" "rsync -rt --exclude '$(basename "${WORLD_FLAG_INRAM[$1]}")' \"${WORLD_RAMDISK_PATH[$1]}/\" \"${WORLD_PATH[$1]}\"" } # Toggles a worlds ramdisk state @@ -189,15 +188,15 @@ world_to_disk() { world_toggle_ramdisk_state() { if [ -f "${WORLD_FLAG_INRAM[$1]}" ]; then echo -n "Removing RAM flag from world \"${WORLD_NAME[$1]}\"... " - as_user "${SERVER_USER_NAME[${WORLD_SERVER_ID[$1]}]}" "rm -f \"${WORLD_FLAG_INRAM[$1]}\"" + as_user "${SERVER_USERNAME[${WORLD_SERVER_ID[$1]}]}" "rm -f \"${WORLD_FLAG_INRAM[$1]}\"" echo "Done." echo -n "Removing world \"${WORLD_NAME[$1]}\" from RAM... " - as_user "${SERVER_USER_NAME[${WORLD_SERVER_ID[$1]}]}" "rm -r \"${WORLD_RAMDISK_PATH[$1]}\"" + as_user "${SERVER_USERNAME[${WORLD_SERVER_ID[$1]}]}" "rm -r \"${WORLD_RAMDISK_PATH[$1]}\"" echo "Done." else echo -n "Adding RAM flag to world \"${WORLD_NAME[$1]}\"... " - as_user "${SERVER_USER_NAME[${WORLD_SERVER_ID[$1]}]}" "touch \"${WORLD_FLAG_INRAM[$1]}\"" + as_user "${SERVER_USERNAME[${WORLD_SERVER_ID[$1]}]}" "touch \"${WORLD_FLAG_INRAM[$1]}\"" echo "Done." echo -n "Copying world to RAM... " @@ -216,7 +215,7 @@ world_backup() { local server_id="${WORLD_SERVER_ID[$1]}" local containing_dir="$(dirname "${WORLD_PATH[$1]}")" local dir_name="$(basename "${WORLD_PATH[$1]}")" - as_user "${SERVER_USER_NAME[$server_id]}" "mkdir -p \"${WORLD_BACKUP_PATH[$1]}\" && cd \"$containing_dir\" && zip -rq \"${WORLD_BACKUP_PATH[$1]}/${file_name}\" \"${dir_name}\"" + as_user "${SERVER_USERNAME[$server_id]}" "mkdir -p \"${WORLD_BACKUP_PATH[$1]}\" && cd \"$containing_dir\" && zip -rq \"${WORLD_BACKUP_PATH[$1]}/${file_name}\" \"${dir_name}\"" echo "Done." } @@ -227,7 +226,7 @@ world_activate() { if [ -d "${WORLD_INACTIVE_PATH[$1]}" ]; then echo -n "Moving world \"${WORLD_NAME[$1]}\" to the active worldstorage directory... " local new_path="${WORLD_ACTIVE_PATH[$1]}" - as_user "${SERVER_USER_NAME[${WORLD_SERVER_ID[$1]}]}" "mkdir -p \"$new_path\" && mv \"${WORLD_INACTIVE_PATH[$1]}\" \"$new_path\"" + as_user "${SERVER_USERNAME[${WORLD_SERVER_ID[$1]}]}" "mkdir -p \"$new_path\" && mv \"${WORLD_INACTIVE_PATH[$1]}\" \"$new_path\"" echo "Done." else if [ -d "${WORLD_ACTIVE_PATH[$1]}" ]; then @@ -247,7 +246,7 @@ world_deactivate() { if [ -d "${WORLD_ACTIVE_PATH[$1]}" ]; then echo -n "Moving world \"${WORLD_NAME[$1]}\" to the inactive worldstorage directory... " local new_path="${WORLD_INACTIVE_PATH[$1]}" - as_user "${SERVER_USER_NAME[${WORLD_SERVER_ID[$1]}]}" "mkdir -p \"$new_path\" && mv \"${WORLD_PATH[$1]}\" \"$new_path\"" + as_user "${SERVER_USERNAME[${WORLD_SERVER_ID[$1]}]}" "mkdir -p \"$new_path\" && mv \"${WORLD_PATH[$1]}\" \"$new_path\"" echo "Done." else if [ -d "${WORLD_INACTIVE_PATH[$1]}" ]; then @@ -280,7 +279,7 @@ server_get_id() { # $1: The ID of the server # $2: The name of the world server_world_get_id() { - if [ -d "${SERVER_WORLD_STORAGE[$1]}/$2" ] || [ -d "${SERVER_WORLD_STORAGE_INACTIVE[$1]}/$2" ]; then + if [ -d "${SERVER_WORLD_STORAGE_PATH[$1]}/$2" ] || [ -d "${SERVER_WORLD_STORAGE_INACTIVE_PATH[$1]}/$2" ]; then # If the directory exists local start="${SERVER_WORLD_OFFSET[$1]}" @@ -309,7 +308,7 @@ server_is_running() { fi } -# Creates symbolic links in the server directory (SERVER_STORAGE_PATH) for each +# Creates symbolic links in the server directory (SETTINGS_SERVER_STORAGE_PATH) for each # of the Minecraft worlds located in the world storage directory. # $1: The id of the server for which links should be ensured server_ensure_links() { @@ -321,7 +320,7 @@ server_ensure_links() { for ((i=$start; i<$max; i++)); do if [[ "${WORLD_STATUS[$i]}" != "active" ]]; then # Remove the symbolic link if it exists - as_user "${SERVER_USER_NAME[$1]}" "rm -f \"${WORLD_LINK[$i]}\"" + as_user "${SERVER_USERNAME[$1]}" "rm -f \"${WORLD_LINK[$i]}\"" continue fi @@ -343,10 +342,10 @@ server_ensure_links() { # If the symbolic link does not point to the RAM version of the world # Remove the symbolic link if it exists - as_user "${SERVER_USER_NAME[$1]}" "rm -f \"${WORLD_LINK[$i]}\"" + as_user "${SERVER_USERNAME[$1]}" "rm -f \"${WORLD_LINK[$i]}\"" # Create a new symbolic link pointing to the RAM version of the world - as_user "${SERVER_USER_NAME[$1]}" "ln -s \"${WORLD_RAMDISK_PATH[$i]}\" \"${WORLD_LINK[$i]}\"" + as_user "${SERVER_USERNAME[$1]}" "ln -s \"${WORLD_RAMDISK_PATH[$i]}\" \"${WORLD_LINK[$i]}\"" fi else # Otherwise the world is not loaded into RAM, and is just on disk @@ -355,10 +354,10 @@ server_ensure_links() { # If the symbolic link does not point to the disk version of the world # Remove the symbolic link if it exists - as_user "${SERVER_USER_NAME[$1]}" "rm -f \"${WORLD_LINK[$i]}\"" + as_user "${SERVER_USERNAME[$1]}" "rm -f \"${WORLD_LINK[$i]}\"" # Create a new symbolic link pointing to the disk version of the world - as_user "${SERVER_USER_NAME[$1]}" "ln -s \"${WORLD_PATH[$i]}\" \"${WORLD_LINK[$i]}\"" + as_user "${SERVER_USERNAME[$1]}" "ln -s \"${WORLD_PATH[$i]}\" \"${WORLD_LINK[$i]}\"" fi fi else @@ -378,7 +377,7 @@ server_ensure_links() { # $1: The ID of the server server_worlds_to_ram() { # Only proceed if there is a ramdisk path set in config - if [ ! -z "$RAMDISK_STORAGE_PATH" ]; then + if [ ! -z "$SETTINGS_RAMDISK_STORAGE_PATH" ]; then echo -n "Synchronising flagged worlds on disk to RAM... " local i="${SERVER_WORLD_OFFSET[$1]}" local max="$(( $i + ${SERVER_NUM_WORLDS[$1]} ))" @@ -398,7 +397,7 @@ server_worlds_to_ram() { # Moves a servers "in RAM" worlds back to disk # $1: The ID of the server server_worlds_to_disk() { - if [ ! -z "$RAMDISK_STORAGE_PATH" ]; then + if [ ! -z "$SETTINGS_RAMDISK_STORAGE_PATH" ]; then echo -n "Synchronising worlds in RAM to disk... " local i="${SERVER_WORLD_OFFSET[$1]}" local max="$(( $i + ${SERVER_NUM_WORLDS[$1]} ))" @@ -422,7 +421,7 @@ server_worlds_to_disk() { # returns: When the line is found server_log_get_line() { # Make sure there is a server log to check - as_user "${SERVER_USER_NAME[$1]}" "touch ${SERVER_LOG[$1]}" + as_user "${SERVER_USERNAME[$1]}" "touch ${SERVER_LOG_PATH[$1]}" while read line; do line_time="$(log_line_get_time "$line")" @@ -438,7 +437,7 @@ server_log_get_line() { fi done fi - done < <(as_user "${SERVER_USER_NAME[$1]}" "tail --pid=$$ --follow --lines=100 --sleep-interval=0.1 \"${SERVER_LOG[$1]}\"") + done < <(as_user "${SERVER_USERNAME[$1]}" "tail --pid=$$ --follow --lines=100 --sleep-interval=0.1 \"${SERVER_LOG_PATH[$1]}\"") } # The same as server_log_get_line, but does not print the line to stdout @@ -451,7 +450,7 @@ server_log_wait_for_line() { # $1: The ID of the server # $2: The line of text to enter into the server console server_eval() { - as_user "${SERVER_USER_NAME[$1]}" "screen -p 0 -S ${SERVER_SCREEN_NAME[$1]} -X eval 'stuff \"$2\"\015'" + as_user "${SERVER_USERNAME[$1]}" "screen -p 0 -S ${SERVER_SCREEN_NAME[$1]} -X eval 'stuff \"$2\"\015'" } # The same as server_eval, but also waits for a log entry before returning @@ -497,11 +496,11 @@ server_wait_for_stop() { server_set_active() { case "$2" in active) - as_user "${SERVER_USER_NAME[$1]}" "touch \"${SERVER_FLAG_ACTIVE[$1]}\"" + as_user "${SERVER_USERNAME[$1]}" "touch \"${SERVER_FLAG_ACTIVE[$1]}\"" SERVER_ACTIVE[$1]="true" ;; inactive) - as_user "${SERVER_USER_NAME[$1]}" "rm -f \"${SERVER_FLAG_ACTIVE[$1]}\"" + as_user "${SERVER_USERNAME[$1]}" "rm -f \"${SERVER_FLAG_ACTIVE[$1]}\"" SERVER_ACTIVE[$1]="false" ;; *) @@ -515,7 +514,7 @@ server_set_active() { # Lists the jar files grouped by jar groups. jargroup_list() { - if [[ -d "${JAR_STORAGE_PATH}" ]]; then + if [[ -d "${SETTINGS_JAR_STORAGE_PATH}" ]]; then local jargroup_name local jar_name @@ -527,8 +526,8 @@ jargroup_list() { if [[ "$jar_name" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}- ]]; then echo " $jar_name" fi - done < <(find "${JAR_STORAGE_PATH}/${jargroup_name}" -mindepth 1 -maxdepth 1 -type f -print0) - done < <(find "${JAR_STORAGE_PATH}" -mindepth 1 -maxdepth 1 -type d -print0) + done < <(find "${SETTINGS_JAR_STORAGE_PATH}/${jargroup_name}" -mindepth 1 -maxdepth 1 -type f -print0) + done < <(find "${SETTINGS_JAR_STORAGE_PATH}" -mindepth 1 -maxdepth 1 -type d -print0) fi } @@ -536,16 +535,16 @@ jargroup_list() { # $1: The name for the jargroup jargroup_create() { if is_valid_name "$1"; then - if [[ ! -d "$JAR_STORAGE_PATH/$1" ]]; then + if [[ ! -d "$SETTINGS_JAR_STORAGE_PATH/$1" ]]; then printf "Creating jar group... " - local error="$(as_user_stderr "$USERNAME" "mkdir -p \"$JAR_STORAGE_PATH/$1\"")" + local error="$(as_user_stderr "$SETTINGS_USERNAME" "mkdir -p \"$SETTINGS_JAR_STORAGE_PATH/$1\"")" if [[ "$error" != "" ]]; then echo "Failed." error_exit FILE_NOT_FOUND "$error" fi - error="$(as_user "$USERNAME" "echo \"$2\" > \"$JAR_STORAGE_PATH/$1/$JARGROUP_TARGET\"")" + error="$(as_user "$SETTINGS_USERNAME" "echo \"$2\" > \"$SETTINGS_JAR_STORAGE_PATH/$1/$SETTINGS_JARGROUP_TARGET\"")" if [[ "$error" != "" ]]; then echo "Failed." error_exit FILE_NOT_FOUND "$error" @@ -565,31 +564,31 @@ jargroup_create() { # $1: The jargroup name to download the latest version for jargroup_getlatest() { if is_valid_name "$1"; then - if [[ -d "$JAR_STORAGE_PATH/$1" ]]; then - if [[ -f "$JAR_STORAGE_PATH/$1/$JARGROUP_TARGET" ]]; then + if [[ -d "$SETTINGS_JAR_STORAGE_PATH/$1" ]]; then + if [[ -f "$SETTINGS_JAR_STORAGE_PATH/$1/$SETTINGS_JARGROUP_TARGET" ]]; then printf "Downloading latest version... " # Try and make - local error="$(as_user_stderr "$USERNAME" "mkdir -p '$JAR_STORAGE_PATH/$1/$JARGROUP_DOWNLOAD_DIR'")" + local error="$(as_user_stderr "$SETTINGS_USERNAME" "mkdir -p '$SETTINGS_JAR_STORAGE_PATH/$1/$SETTINGS_JARGROUP_DOWNLOAD_DIR'")" if [[ "$error" != "" ]]; then echo "Failed." error_exit FILE_NOT_FOUND "$error" fi - as_user "$USERNAME" "wget --quiet --trust-server-names --no-check-certificate --input-file='$JAR_STORAGE_PATH/$1/$JARGROUP_TARGET' --directory-prefix='$JAR_STORAGE_PATH/$1/$JARGROUP_DOWNLOAD_DIR'" + as_user "$SETTINGS_USERNAME" "wget --quiet --trust-server-names --no-check-certificate --input-file='$SETTINGS_JAR_STORAGE_PATH/$1/$SETTINGS_JARGROUP_TARGET' --directory-prefix='$SETTINGS_JAR_STORAGE_PATH/$1/$SETTINGS_JARGROUP_DOWNLOAD_DIR'" echo "Done." - local num_files="$(as_user "$USERNAME" "ls -1 '$JAR_STORAGE_PATH/$1/$JARGROUP_DOWNLOAD_DIR' | wc -l")" + local num_files="$(as_user "$SETTINGS_USERNAME" "ls -1 '$SETTINGS_JAR_STORAGE_PATH/$1/$SETTINGS_JARGROUP_DOWNLOAD_DIR' | wc -l")" if [[ "$num_files" == 1 ]]; then # There was 1 file downloaded - local file_name="$(ls -1 "$JAR_STORAGE_PATH/$1/$JARGROUP_DOWNLOAD_DIR")" + local file_name="$(ls -1 "$SETTINGS_JAR_STORAGE_PATH/$1/$SETTINGS_JARGROUP_DOWNLOAD_DIR")" local new_name="$(date +%F-%H-%M-%S)-$file_name" - local most_recent_jar="$(get_latest_file "$JAR_STORAGE_PATH/$1")" + local most_recent_jar="$(get_latest_file "$SETTINGS_JAR_STORAGE_PATH/$1")" - if [[ ! -f "$most_recent_jar" ]] || ! diff "$most_recent_jar" "$JAR_STORAGE_PATH/$1/$JARGROUP_DOWNLOAD_DIR/$file_name" > /dev/null; then + if [[ ! -f "$most_recent_jar" ]] || ! diff "$most_recent_jar" "$SETTINGS_JAR_STORAGE_PATH/$1/$SETTINGS_JARGROUP_DOWNLOAD_DIR/$file_name" > /dev/null; then # There is not a previous version to do a comparison against, or # The previous version is different: # Add it to the group @@ -597,15 +596,15 @@ jargroup_getlatest() { [[ -f "$most_recent_jar" ]] local was_previous="$?" - as_user "$USERNAME" "mv '$JAR_STORAGE_PATH/$1/$JARGROUP_DOWNLOAD_DIR/$file_name' '$JAR_STORAGE_PATH/$1/$new_name'" + as_user "$SETTINGS_USERNAME" "mv '$SETTINGS_JAR_STORAGE_PATH/$1/$SETTINGS_JARGROUP_DOWNLOAD_DIR/$file_name' '$SETTINGS_JAR_STORAGE_PATH/$1/$new_name'" if [[ ! -z "$most_recent_jar" ]]; then - echo "Downloaded version was different to previous latest. Saved as \"$JAR_STORAGE_PATH/$1/$new_name\"." + echo "Downloaded version was different to previous latest. Saved as \"$SETTINGS_JAR_STORAGE_PATH/$1/$new_name\"." else - echo "Saved as \"$JAR_STORAGE_PATH/$1/$new_name\"." + echo "Saved as \"$SETTINGS_JAR_STORAGE_PATH/$1/$new_name\"." fi else - echo "Existing version \"$JAR_STORAGE_PATH/$1/$new_name\" was already up to date." + echo "Existing version \"$SETTINGS_JAR_STORAGE_PATH/$1/$new_name\" was already up to date." fi elif [[ "$num_files" == 0 ]]; then @@ -617,7 +616,7 @@ jargroup_getlatest() { fi # Clean up the temp download folder - as_user "$USERNAME" "rm -fr '$JAR_STORAGE_PATH/$1/$JARGROUP_DOWNLOAD_DIR'" + as_user "$SETTINGS_USERNAME" "rm -fr '$SETTINGS_JAR_STORAGE_PATH/$1/$SETTINGS_JARGROUP_DOWNLOAD_DIR'" else error_exit FILE_NOT_FOUND "Target URL not found, use $0 jargroup seturl " fi @@ -631,12 +630,12 @@ jargroup_getlatest() { # $1: The name of the existing jargroup jargroup_delete() { if is_valid_name "$1"; then - if [[ -d "$JAR_STORAGE_PATH/$1" ]]; then + if [[ -d "$SETTINGS_JAR_STORAGE_PATH/$1" ]]; then printf "Are you sure you want to delete this jar group [y/N]: " read answer if [[ "$answer" =~ ^y|Y|yes$ ]]; then - as_user "$USERNAME" "rm -rf \"$JAR_STORAGE_PATH/$1\"" + as_user "$SETTINGS_USERNAME" "rm -rf \"$SETTINGS_JAR_STORAGE_PATH/$1\"" echo "Jar group deleted." else echo "Jar group was NOT deleted." @@ -652,16 +651,16 @@ jargroup_delete() { # $2: The new name jargroup_rename() { if is_valid_name "$1"; then - if [[ -d "$JAR_STORAGE_PATH/$1" ]]; then + if [[ -d "$SETTINGS_JAR_STORAGE_PATH/$1" ]]; then # If the jar group name is valid, # and there is no other jar group with the name $1 if is_valid_name "$2"; then - if [[ -e "$JAR_STORAGE_PATH/$2" ]]; then + if [[ -e "$SETTINGS_JAR_STORAGE_PATH/$2" ]]; then error_exit DUPLICATE_NAME "Could not be renamed, there is already a jar group with the name \"$2\"." else # TODO: Update any symbolic links which point to a jar in this directory - as_user "$USERNAME" "mv '$JAR_STORAGE_PATH/$1' '$JAR_STORAGE_PATH/$2'" + as_user "$SETTINGS_USERNAME" "mv '$SETTINGS_JAR_STORAGE_PATH/$1' '$SETTINGS_JAR_STORAGE_PATH/$2'" echo "Renamed jar group \"$1\" to \"$2\"." fi fi @@ -674,10 +673,10 @@ jargroup_rename() { ### Server Functions -# Echos a list of servers in the SERVER_STORAGE_PATH +# Echos a list of servers in the SETTINGS_SERVER_STORAGE_PATH server_list() { - if [ -d "$SERVER_STORAGE_PATH" ]; then - ls -1 "$SERVER_STORAGE_PATH" + if [ -d "$SETTINGS_SERVER_STORAGE_PATH" ]; then + ls -1 "$SETTINGS_SERVER_STORAGE_PATH" else echo "[There are no servers]" fi @@ -687,18 +686,18 @@ server_list() { # $1: The server name to create server_create() { if is_valid_name "$1"; then - if [[ -d "$SERVER_STORAGE_PATH/$1" ]]; then + if [[ -d "$SETTINGS_SERVER_STORAGE_PATH/$1" ]]; then error_exit DUPLICATE_NAME "A server with that name already exists." else printf "Creating server directory... " - as_user "$USERNAME" "mkdir -p '$SERVER_STORAGE_PATH/$1'" - as_user "$USERNAME" "touch '$SERVER_STORAGE_PATH/$1/$DEFAULT_WHITELIST'" - as_user "$USERNAME" "touch '$SERVER_STORAGE_PATH/$1/$DEFAULT_BANNED_IPS'" - as_user "$USERNAME" "touch '$SERVER_STORAGE_PATH/$1/$DEFAULT_BANNED_PLAYERS'" - as_user "$USERNAME" "touch '$SERVER_STORAGE_PATH/$1/$DEFAULT_OPS'" - as_user "$USERNAME" "touch '$SERVER_STORAGE_PATH/$1/$DEFAULT_PROPERTIES'" - as_user "$USERNAME" "mkdir -p '$SERVER_STORAGE_PATH/$1/$DEFAULT_WORLD_STORAGE_PATH'" - as_user "$USERNAME" "echo \"MSM requires all your worlds be moved into this directory.\" > '$SERVER_STORAGE_PATH/$1/$DEFAULT_WORLD_STORAGE_PATH/readme.txt'" + as_user "$SETTINGS_USERNAME" "mkdir -p '$SETTINGS_SERVER_STORAGE_PATH/$1'" + as_user "$SETTINGS_USERNAME" "touch '$SETTINGS_SERVER_STORAGE_PATH/$1/$SETTINGS_DEFAULT_WHITELIST_PATH'" + as_user "$SETTINGS_USERNAME" "touch '$SETTINGS_SERVER_STORAGE_PATH/$1/$SETTINGS_DEFAULT_BANNED_IPS_PATH'" + as_user "$SETTINGS_USERNAME" "touch '$SETTINGS_SERVER_STORAGE_PATH/$1/$SETTINGS_DEFAULT_BANNED_PLAYERS_PATH'" + as_user "$SETTINGS_USERNAME" "touch '$SETTINGS_SERVER_STORAGE_PATH/$1/$SETTINGS_DEFAULT_OPS_PATH'" + as_user "$SETTINGS_USERNAME" "touch '$SETTINGS_SERVER_STORAGE_PATH/$1/$SETTINGS_SERVER_PROPERTIES'" + as_user "$SETTINGS_USERNAME" "mkdir -p '$SETTINGS_SERVER_STORAGE_PATH/$1/$SETTINGS_DEFAULT_WORLD_STORAGE_PATH'" + as_user "$USERNAME" "echo \"MSM requires all your worlds be moved into this directory.\" > '$SETTINGS_SERVER_STORAGE_PATH/$1/$SETTINGS_DEFAULT_WORLD_STORAGE_PATH/readme.txt'" echo "Done." # Now that the new server has been created, we must call init again @@ -707,7 +706,7 @@ server_create() { # TODO: Handle server default setup stuff better than just using # the "minecraft" jar group. And make it configurable. - if [ -d "$JAR_STORAGE_PATH/minecraft" ]; then + if [ -d "$SETTINGS_JAR_STORAGE_PATH/minecraft" ]; then server_set_jar "$(server_get_id "$1")" "minecraft" fi fi @@ -718,13 +717,13 @@ server_create() { # $1: The server name to delete server_delete() { if is_valid_name "$1"; then - if [[ -d "$SERVER_STORAGE_PATH/$1" ]]; then + if [[ -d "$SETTINGS_SERVER_STORAGE_PATH/$1" ]]; then printf "Are you sure you want to delete this server and its worlds (note: backups are preserved) [y/N]: " read answer if [[ "$answer" =~ ^(y|Y|yes)$ ]]; then # TODO: stop the server if running first - as_user "$USERNAME" "rm -rf '$SERVER_STORAGE_PATH/$1'" + as_user "$SETTINGS_USERNAME" "rm -rf '$SETTINGS_SERVER_STORAGE_PATH/$1'" echo "Server deleted." else echo "Server was NOT deleted." @@ -740,7 +739,7 @@ server_delete() { # $2: The new name for the server server_rename() { if is_valid_name "$1"; then - if [ -d "$SERVER_STORAGE_PATH/$1" ]; then + if [ -d "$SETTINGS_SERVER_STORAGE_PATH/$1" ]; then # If the server name is valid and exists local existing_id="$(server_get_id "$1")" @@ -749,11 +748,11 @@ server_rename() { else if is_valid_name "$2"; then # If the server name is valid - if [[ -e "$SERVER_STORAGE_PATH/$2" ]]; then + if [[ -e "$SETTINGS_SERVER_STORAGE_PATH/$2" ]]; then # and there is not already a server with the name $2 error_exit DUPLICATE_NAME "Could not be renamed, there is already a server with the name \"$2\"." else - as_user "$USERNAME" "mv '$SERVER_STORAGE_PATH/$1' '$SERVER_STORAGE_PATH/$2'" + as_user "$SETTINGS_USERNAME" "mv '$SETTINGS_SERVER_STORAGE_PATH/$1' '$SETTINGS_SERVER_STORAGE_PATH/$2'" echo "Renamed server \"$1\" to \"$2\"." fi fi @@ -776,7 +775,7 @@ server_start() { local time_now="$(now)" printf "Starting server... " - as_user "${SERVER_USER_NAME[$1]}" "cd \"${SERVER_PATH[$1]}\" && screen -dmS \"${SERVER_SCREEN_NAME[$1]}\" ${SERVER_INVOCATION[$1]}" + as_user "${SERVER_USERNAME[$1]}" "cd \"${SERVER_PATH[$1]}\" && screen -dmS \"${SERVER_SCREEN_NAME[$1]}\" ${SERVER_INVOCATION[$1]}" server_log_wait_for_line "$1" "$time_now" "${SERVER_CONFIRM_START[$1]}" echo "Done." @@ -838,8 +837,8 @@ server_stop() { # Change the state of the script STOP_COUNTDOWN[$1]="true" - server_eval "$1" "say ${SERVER_STOP_MESSAGE[$1]}" - echo "Issued the warning \"${SERVER_STOP_MESSAGE[$1]}\" to players." + server_eval "$1" "say ${SERVER_MESSAGE_STOP[$1]}" + echo "Issued the warning \"${SERVER_MESSAGE_STOP[$1]}\" to players." echo -n "Shutting down... " @@ -889,8 +888,8 @@ server_restart() { # Change the state of the script RESTART_COUNTDOWN[$1]="true" - server_eval "$1" "say ${SERVER_RESTART_MESSAGE[$1]}" - echo "Issued the warning \"${SERVER_RESTART_MESSAGE[$1]}\" to players." + server_eval "$1" "say ${SERVER_MESSAGE_RESTART[$1]}" + echo "Issued the warning \"${SERVER_MESSAGE_RESTART[$1]}\" to players." echo -n "Restarting... " @@ -963,13 +962,13 @@ server_log_roll() { printf "Rolling server logs... " - if [ -e "${SERVER_LOG[$1]}" ]; then + if [ -e "${SERVER_LOG_PATH[$1]}" ]; then file_name="${SERVER_NAME[$1]}-$(date +%F-%H-%M-%S).log" - as_user "${SERVER_USER_NAME[$1]}" "mkdir -p \"${SERVER_LOG_archive_path[$1]}\" && cp \"${SERVER_LOG[$1]}\" \"${SERVER_LOG_archive_path[$1]}/${file_name}\" && gzip \"${SERVER_LOG_archive_path[$1]}/${file_name}\"" + as_user "${SERVER_USERNAME[$1]}" "mkdir -p \"${SERVER_LOG_ARCHIVE_PATH[$1]}\" && cp \"${SERVER_LOG_PATH[$1]}\" \"${SERVER_LOG_ARCHIVE_PATH[$1]}/${file_name}\" && gzip \"${SERVER_LOG_ARCHIVE_PATH[$1]}/${file_name}\"" - if [ -e "${SERVER_LOG_archive_path[$1]}/${file_name}.gz" ]; then - as_user "${SERVER_USER_NAME[$1]}" "cp \"/dev/null\" \"${SERVER_LOG[$1]}\"" - as_user "${SERVER_USER_NAME[$1]}" "echo \"Previous logs can be found at \\\"${SERVER_LOG_archive_path[$1]}\\\"\" > \"${SERVER_LOG[$1]}\"" + if [ -e "${SERVER_LOG_ARCHIVE_PATH[$1]}/${file_name}.gz" ]; then + as_user "${SERVER_USERNAME[$1]}" "cp \"/dev/null\" \"${SERVER_LOG_PATH[$1]}\"" + as_user "${SERVER_USERNAME[$1]}" "echo \"Previous logs can be found at \\\"${SERVER_LOG_ARCHIVE_PATH[$1]}\\\"\" > \"${SERVER_LOG_PATH[$1]}\"" else echo "Failed." error_exit LOGS_NOT_ROLLED "Logs were not rolled." @@ -992,7 +991,7 @@ server_backup() { # Zip up the server directory file_name="${SERVER_BACKUP_PATH[$1]}/$(date "+%F-%H-%M-%S").zip" - as_user "${SERVER_USER_NAME[$1]}" "mkdir -p \"${SERVER_BACKUP_PATH[$1]}\" && cd \"$SERVER_STORAGE_PATH\" && zip ${zip_flags} \"${file_name}\" \"${SERVER_NAME[$1]}\"" + as_user "${SERVER_USERNAME[$1]}" "mkdir -p \"${SERVER_BACKUP_PATH[$1]}\" && cd \"$SETTINGS_SERVER_STORAGE_PATH\" && zip ${zip_flags} \"${file_name}\" \"${SERVER_NAME[$1]}\"" echo "Done." } @@ -1002,17 +1001,17 @@ server_backup() { # $2: The name of the jar group # $3: Optionally, a specific jar to use. server_set_jar() { - if [ -d "$JAR_STORAGE_PATH/$2" ]; then + if [ -d "$SETTINGS_JAR_STORAGE_PATH/$2" ]; then if [ -z "$3" ]; then # If a specific jar file is not mentioned # Download the latest version jargroup_getlatest "$2" - local jar="$(get_latest_file "$JAR_STORAGE_PATH/$2")" + local jar="$(get_latest_file "$SETTINGS_JAR_STORAGE_PATH/$2")" else # If a specific jar IS mentioned use that - local jar="$JAR_STORAGE_PATH/$2/$3" + local jar="$SETTINGS_JAR_STORAGE_PATH/$2/$3" if [[ ! -e "$jar" ]]; then error_exit NAME_NOT_FOUND "There is no jar named \"$3\" in jargroup \"$2\"." @@ -1020,7 +1019,7 @@ server_set_jar() { fi if [[ ! -z "$jar" ]]; then - as_user "${SERVER_USER_NAME[$1]}" "ln -sf \"$jar\" \"${SERVER_JAR[$1]}\"" + as_user "${SERVER_USERNAME[$1]}" "ln -sf \"$jar\" \"${SERVER_JAR_PATH[$1]}\"" echo "Server \"${SERVER_NAME[$1]}\" is now using \"$jar\"." fi else @@ -1047,6 +1046,13 @@ server_connected() { fi } +# Get the value of a server property +# $1: The ID of the server +# $2: The name of the server property +server_property() { + eval echo "\${SERVER_$2[$1]}" +} + ### Manager Functions @@ -1074,16 +1080,16 @@ manager_stop_all_servers() { # Send a warning message to the server case "$1" in - stop) server_eval "$server" "say ${SERVER_STOP_MESSAGE[$server]}";; - restart) server_eval "$server" "say ${SERVER_RESTART_MESSAGE[$server]}";; + stop) server_eval "$server" "say ${SERVER_MESSAGE_STOP[$server]}";; + restart) server_eval "$server" "say ${SERVER_MESSAGE_RESTART[$server]}";; esac # Send message to stdout echo "Server \"${SERVER_NAME[$server]}\" was running, now stopping:" case "$1" in - stop) echo " Issued the warning \"${SERVER_STOP_MESSAGE[$server]}\" to players.";; - restart) echo " Issued the warning \"${SERVER_RESTART_MESSAGE[$server]}\" to players.";; + stop) echo " Issued the warning \"${SERVER_MESSAGE_STOP[$server]}\" to players.";; + restart) echo " Issued the warning \"${SERVER_MESSAGE_RESTART[$server]}\" to players.";; esac case "${SERVER_STOP_DELAY[$server]}" in @@ -1180,6 +1186,12 @@ manager_stop_all_servers_now() { fi } +# Get the value of a global manager property +# $1: The name of the property +manager_property() { + eval echo "\$SETTINGS_$1" +} + ### Command Functions @@ -1244,6 +1256,13 @@ command_version() { echo "Minecraft Server Manager $version" } +# Displays config values used by MSM +command_config() { + for ((i=0; i<$SETTING_COUNT; i++)); do + echo "${SETTING_NAME[$i]}=\"$(manager_property "${SETTING_NAME[$i]}")\"" + done +} + # Displays a list of servers command_server_list() { server_list @@ -1354,7 +1373,7 @@ command_help() { echo -e " cmd Send a command string to the server and return" echo -e " cmdlog Same as 'cmd' but shows log output afterwards (Ctrl+C to exit)" echo -e " console Connects to the interactive console. Access may be limited" - echo -e " config Updates or inserts a setting in the server.properties file" + echo -e " config [ ] Lists server settings, or sets a specific setting." echo -e echo -e "--Jar Commands--------------------------------------------------" echo -e " jargroup list List the stored jar files." @@ -1369,6 +1388,7 @@ command_help() { echo -e " stop [now] Stops all running servers" echo -e " restart [now] Restarts all active servers" echo -e " version Prints the Minecraft Server Manager version installed" + echo -e " config Displays a list of the config values used by MSM" } # Starts an individual server @@ -1459,7 +1479,7 @@ command_server_worlds_todisk() { # $1: The server ID command_server_worlds_backup() { if server_is_running "$1"; then - server_eval "$1" "say ${SERVER_WORLD_BACKUP_STARTED[$1]}" + server_eval "$1" "say ${SERVER_MESSAGE_WORLD_BACKUP_STARTED[$1]}" server_save_off "$1" server_save_all "$1" fi @@ -1469,7 +1489,7 @@ command_server_worlds_backup() { if server_is_running "$1"; then server_save_on "$1" - server_eval "$1" "say ${SERVER_WORLD_BACKUP_FINISHED[$1]}" + server_eval "$1" "say ${SERVER_MESSAGE_WORLD_BACKUP_FINISHED[$1]}" fi echo "Backup took $SECONDS seconds". @@ -1500,7 +1520,7 @@ command_server_logroll() { # $1: The server ID command_server_backup() { if server_is_running "$1"; then - server_eval "$1" "say ${SERVER_COMPLETE_BACKUP_STARTED[$1]}" + server_eval "$1" "say ${SERVER_MESSAGE_COMPLETE_BACKUP_STARTED[$1]}" server_save_off "$1" server_save_all "$1" fi @@ -1510,7 +1530,7 @@ command_server_backup() { if server_is_running "$1"; then server_save_on "$1" - server_eval "$1" "say ${SERVER_COMPLETE_BACKUP_FINISHED[$1]}" + server_eval "$1" "say ${SERVER_MESSAGE_COMPLETE_BACKUP_FINISHED[$1]}" fi echo "Backup took $SECONDS seconds". @@ -1576,8 +1596,8 @@ command_server_whitelist_remove() { # Displays a list of whitelisted players for an individual server # $1: The server ID command_server_whitelist_list() { - if [ -f "${SERVER_WHITELIST[$1]}" ]; then - local players="$(cat "${SERVER_WHITELIST[$1]}")" + if [ -f "${SERVER_WHITELIST_PATH[$1]}" ]; then + local players="$(cat "${SERVER_WHITELIST_PATH[$1]}")" if [ -z "$players" ]; then echo "No players are whitelisted." @@ -1675,12 +1695,12 @@ command_server_blacklist_list() { local players local ips - if [ -f "${SERVER_BANNED_PLAYERS[$1]}" ]; then - players="$(cat "${SERVER_BANNED_PLAYERS[$1]}")" + if [ -f "${SERVER_BANNED_PLAYERS_PATH[$1]}" ]; then + players="$(cat "${SERVER_BANNED_PLAYERS_PATH[$1]}")" fi - if [ -f "${SERVER_BANNED_IPS[$1]}" ]; then - ips="$(cat "${SERVER_BANNED_IPS[$1]}")" + if [ -f "${SERVER_BANNED_IPS_PATH[$1]}" ]; then + ips="$(cat "${SERVER_BANNED_IPS_PATH[$1]}")" fi if [[ -z "$players" && -z "$ips" ]]; then @@ -1732,7 +1752,7 @@ command_server_operator_remove() { # $1: The server ID command_server_operator_list() { # TODO: Protect against non-existent files - local players="$(cat "${SERVER_OPS[$1]}")" + local players="$(cat "${SERVER_OPS_PATH[$1]}")" if [ -z "$players" ]; then echo "No players are operators." @@ -1967,7 +1987,7 @@ command_server_cmdlog() { if server_is_running "$1"; then server_eval "$1" "${*:2}" echo "Now watching logs (press Ctrl+C to exit):" - as_user "${SERVER_USER_NAME[$1]}" "tail --pid=$$ --follow --lines=0 --sleep-interval=0.1 ${SERVER_LOG[$1]}" + as_user "${SERVER_USERNAME[$1]}" "tail --pid=$$ --follow --lines=0 --sleep-interval=0.1 ${SERVER_LOG_PATH[$1]}" else error_exit SERVER_STOPPED "Server \"${SERVER_NAME[$1]}\" is not running." fi @@ -1978,7 +1998,7 @@ command_server_cmdlog() { # $1: The server ID command_server_console() { if server_is_running "$1"; then - as_user "${SERVER_USER_NAME[$1]}" "screen -r ${SERVER_SCREEN_NAME[$1]}" + as_user "${SERVER_USERNAME[$1]}" "screen -r ${SERVER_SCREEN_NAME[$1]}" else error_exit SERVER_STOPPED "Server \"${SERVER_NAME[$1]}\" is not running." fi @@ -1987,20 +2007,42 @@ command_server_console() { # Sets a parameter in the config file if it exists, otherwise inserts the # paramerter. # $1: The server ID -# $2: The parameter -# $3: The value to set it to -command_set_config() { - if [[ -f "${SERVER_CONF[$1]}" ]]; then - if grep "$2" ${SERVER_CONF[$1]} >/dev/null; then - sed -i /$2=/s/.*/"$2=$3"/g ${SERVER_CONF[$1]} - else - echo "$2=$3" >> ${SERVER_CONF[$1]} - fi +# $2: Optionally, a setting name +# $3: Optionally, a value to set for $2 +command_server_config() { + # If both a setting name and value are given + if [ ! -z "$2" ] && [ ! -z "$3" ]; then + if [[ -f "${SERVER_CONF[$1]}" ]]; then + if grep "$2" "${SERVER_CONF[$1]}" >/dev/null; then + sed -i /$2=/s/.*/"$2=$3"/g "${SERVER_CONF[$1]}" + else + echo "$2=$3" >> "${SERVER_CONF[$1]}" + fi - if server_is_running "$1"; then - echo "Changes to config may require a server restart to take effect: sudo $0 ${SERVER_NAME[$1]} restart"; + if server_is_running "$1"; then + echo "Changes to config may require a server restart to take effect: sudo $0 ${SERVER_NAME[$1]} restart"; + fi fi fi + + # If only a setting name is given + if [ ! -z "$2" ]; then + + # Convert name into upper-case with underscores + local setting_name="$(echo "$2" | tr '[a-z\-]' '[A-Z\_]')" + + # Display the value of that setting + echo "$(server_property "$1" "$setting_name")" + fi + + # If no paramter name is given + if [ -z "$2" ]; then + # List all parameters + for ((i=0; i<$SERVER_SETTING_COUNT; i++)); do + local setting_name="$(echo "${SERVER_SETTING_NAME[$i]}" | tr '[A-Z\_]' '[a-z\-]')" + echo "msm-$setting_name=\"$(server_property "$1" "${SERVER_SETTING_NAME[$i]}")\"" + done + fi } ### Main Functions @@ -2012,8 +2054,8 @@ command_set_config() { server_world_init() { WORLD_SERVER_ID[$2]="$1" WORLD_NAME[$2]="$3" - WORLD_ACTIVE_PATH[$2]="${SERVER_WORLD_STORAGE[$1]}/${WORLD_NAME[$2]}" - WORLD_INACTIVE_PATH[$2]="${SERVER_WORLD_STORAGE_INACTIVE[$1]}/${WORLD_NAME[$2]}" + WORLD_ACTIVE_PATH[$2]="${SERVER_WORLD_STORAGE_PATH[$1]}/${WORLD_NAME[$2]}" + WORLD_INACTIVE_PATH[$2]="${SERVER_WORLD_STORAGE_INACTIVE_PATH[$1]}/${WORLD_NAME[$2]}" # Set the status of this world (active/inactive) if [ -d "${WORLD_ACTIVE_PATH[$2]}" ]; then @@ -2033,11 +2075,11 @@ server_world_init() { # TODO: Allow the inram flag location to be overridable. WORLD_FLAG_INRAM[$2]="${WORLD_PATH[$2]}/inram" WORLD_LINK[$2]="${SERVER_PATH[$1]}/${WORLD_NAME[$2]}" - WORLD_BACKUP_PATH[$2]="$WORLD_ARCHIVE_PATH/${SERVER_NAME[$1]}/${WORLD_NAME[$2]}" + WORLD_BACKUP_PATH[$2]="$SETTINGS_WORLD_ARCHIVE_PATH/${SERVER_NAME[$1]}/${WORLD_NAME[$2]}" # If the ramdisk path is set, get the path for this world - if [ ! -z "$RAMDISK_STORAGE_PATH" ]; then - WORLD_RAMDISK_PATH[$2]="${RAMDISK_STORAGE_PATH}/${SERVER_NAME[$1]}/${WORLD_NAME[$2]}" + if [ ! -z "$SETTINGS_RAMDISK_STORAGE_PATH" ]; then + WORLD_RAMDISK_PATH[$2]="${SETTINGS_RAMDISK_STORAGE_PATH}/${SERVER_NAME[$1]}/${WORLD_NAME[$2]}" fi # Detect whether this world should be in ram @@ -2048,113 +2090,46 @@ server_world_init() { fi } -# Load a config file for a server -# $1: The id of the server to laod -server_load_config() { +# Load a the server.properties file for a server +# $1: The id of the server to load +server_load_properties() { local name value - if [[ -f "${SERVER_CONF[$1]}" ]]; then + if [[ -f "${SERVER_PATH[$1]}/$SETTINGS_SERVER_PROPERTIES" ]]; then while read line; do # ignore comment lines - echo "$line" | grep "^#" >/dev/null 2>&1 && continue + if [[ "$line" =~ ^# ]]; then + continue + fi - # if not empty, set the property using declare - if [ ! -z "$line" ]; then - name="$(echo $line | awk -F '=' '{print $1}')" - value="$(echo $line | awk -F '=' '{print $2}')" + # if not empty, get the name and value of the setting + if [[ "$line" =~ ^(.*)=(.*)$ ]]; then + name="${BASH_REMATCH[1]}" + value="${BASH_REMATCH[2]}" - # Remove quotations from value - if [[ "$value" =~ ^\"(.*)\" ]]; then - value="${BASH_REMATCH[1]}" - else - if [[ "$value" =~ ^\'(.*)\' ]]; then + # Create variables + if [[ "$name" =~ ^msm-[\-\_a-zA-Z0-9]+$ ]]; then + local name_upper_case="$(echo ${name:4} | tr '[a-z\-]' '[A-Z\_]')" + + if [[ "$name" =~ ^msm-[\-\_a-zA-Z0-9]+-path$ ]]; then + if [[ ! "$value" =~ ^\/ ]]; then + value="${SERVER_PATH[$1]}/$value" + fi + fi + + if [[ "$value" =~ ^\"(.*)\"$ ]] || [[ "$value" =~ ^\'(.*)\'$ ]]; then value="${BASH_REMATCH[1]}" fi + + eval SERVER_${name_upper_case}[$1]=\"$value\" + else + if [[ "$name" =~ ^[\-\_a-zA-Z0-9]+$ ]]; then + local name_upper_case="$(echo $name | tr '[a-z\-\.]' '[A-Z\_\_]')" + eval SERVER_PROPERTIES_${name_upper_case}[$1]=\"$value\" + fi fi fi - - case "$name" in - # Minecraft settings: - allow-flight) SERVER_PROPERTIES_ALLOW_FLIGHT="$value";; - allow-nether) SERVER_PROPERTIES_ALLOW_NETHER="$value";; - difficulty) SERVER_PROPERTIES_DIFFICULTY="$value";; - enable-query) SERVER_PROPERTIES_ENABLE_QUERY="$value";; - enable-rcon) SERVER_PROPERTIES_ENABLE_RCON="$value";; - gamemode) SERVER_PROPERTIES_GAMEMODE="$value";; - generate-structures) SERVER_PROPERTIES_GENERATE_STRUCTURES="$value";; - level-name) SERVER_PROPERTIES_LEVEL_NAME="$value";; - level-seed) SERVER_PROPERTIES_LEVEL_SEED="$value";; - level-type) SERVER_PROPERTIES_LEVEL_TYPE="$value";; - max-build-height) SERVER_PROPERTIES_MAX_BUILD_HEIGHT="$value";; - max-players) SERVER_PROPERTIES_MAX_PLAYERS="$value";; - motd) SERVER_PROPERTIES_MOTD="$value";; - texture-pack) SERVER_PROPERTIES_TEXTURE_PACK="$value";; - online-mode) SERVER_PROPERTIES_ONLINE_MODE="$value";; - pvp) SERVER_PROPERTIES_PVP="$value";; - query.port) SERVER_PROPERTIES_QUERY_PORT="$value";; - rcon.password) SERVER_PROPERTIES_RCON_PASSWORD="$value";; - rcon.port) SERVER_PROPERTIES_RCON_PORT="$value";; - server-ip) SERVER_PROPERTIES_SERVER_IP="$value";; - server-port) SERVER_PROPERTIES_SERVER_PORT="$value";; - spawn-animals) SERVER_PROPERTIES_SPAWN_ANIMALS="$value";; - spawn-monsters) SERVER_PROPERTIES_SPAWN_MONSTERS="$value";; - spawn-npcs) SERVER_PROPERTIES_SPAWN_NPCS="$value";; - view-distance) SERVER_PROPERTIES_VIEW_DISTANCE="$value";; - white-list) SERVER_PROPERTIES_WHITE_LIST="$value";; - - # MSM setttings: - msm-server-user) SERVER_USER_NAME[$1]="$value";; - msm-screen-name) SERVER_SCREEN_NAME[$1]="$value";; - msm-world-storage-path) SERVER_WORLD_STORAGE[$1]="${SERVER_PATH[$1]}/$value";; - msm-world-storage-inactive-path) SERVER_WORLD_STORAGE_INACTIVE[$1]="${SERVER_PATH[$1]}/$value";; - - msm-log) SERVER_LOG[$1]="${SERVER_PATH[$1]}/$value";; - msm-whitelist) SERVER_WHITELIST[$1]="${SERVER_PATH[$1]}/$value";; - msm-banned-players) SERVER_BANNED_PLAYERS[$1]="${SERVER_PATH[$1]}/$value";; - msm-banned-ips) SERVER_BANNED_IPS[$1]="${SERVER_PATH[$1]}/$value";; - - msm-ops) SERVER_OPS[$1]="${SERVER_PATH[$1]}/$value";; - msm-jar) SERVER_JAR[$1]="${SERVER_PATH[$1]}/$value";; - msm-ram) SERVER_RAM[$1]="$value";; - msm-invocation) SERVER_INVOCATION[$1]="$value";; - - msm-stop-delay) SERVER_STOP_DELAY[$1]="$value";; - msm-restart-delay) SERVER_RESTART_DELAY[$1]="$value";; - - msm-stop-message) SERVER_STOP_MESSAGE[$1]="$value";; - msm-stop-abort) SERVER_STOP_ABORT[$1]="$value";; - msm-restart-message) SERVER_RESTART_MESSAGE[$1]="$value";; - msm-restart-abort) SERVER_RESTART_ABORT[$1]="$value";; - msm-world-backup-started) SERVER_WORLD_BACKUP_STARTED[$1]="$value";; - msm-world-backup-finished) SERVER_WORLD_BACKUP_FINISHED[$1]="$value";; - msm-complete-backup-started) SERVER_COMPLETE_BACKUP_STARTED[$1]="$value";; - msm-complete-backup-finished) SERVER_COMPLETE_BACKUP_FINISHED[$1]="$value";; - msm-complete-backup-follow-symlinks) SERVER_COMPLETE_BACKUP_FOLLOW_SYMLINKS[$1]="$value";; - - msm-confirm-save-on) SERVER_CONFIRM_SAVE_ON[$1]="$value";; - msm-confirm-save-off) SERVER_CONFIRM_SAVE_OFF[$1]="$value";; - msm-confirm-save-all) SERVER_CONFIRM_SAVE_ALL[$1]="$value";; - msm-confirm-start) SERVER_CONFIRM_START[$1]="$value";; - msm-confirm-whitelist-list) SERVER_CONFIRM_WHITELIST_LIST[$1]="$value";; - msm-confirm-kick) SERVER_CONFIRM_CONFIRM_KICK[$1]="$value";; - msm-confirm-kick-fail) SERVER_CONFIRM_KICK_FAIL[$1]="$value";; - msm-confirm-time-set) SERVER_CONFIRM_TIME_SET[$1]="$value";; - msm-confirm-time-set-fail) SERVER_CONFIRM_TIME_SET_FAIL[$1]="$value";; - msm-confirm-time-add) SERVER_CONFIRM_TIME_ADD[$1]="$value";; - msm-confirm-time-add-fail) SERVER_CONFIRM_TIME_ADD_FAIL[$1]="$value";; - msm-confirm-toggledownfall) SERVER_CONFIRM_TOGGLEDOWNFALL[$1]="$value";; - msm-confirm-toggledownfall-fail) SERVER_CONFIRM_TOGGLEDOWNFALL_FAIL[$1]="$value";; - msm-confirm-gamemode) SERVER_CONFIRM_GAMEMODE[$1]="$value";; - msm-confirm-gamemode-fail-no-user) SERVER_CONFIRM_GAMEMODE_FAIL_NO_USER[$1]="$value";; - msm-confirm-gamemode-fail-no-change) SERVER_CONFIRM_GAMEMODE_FAIL_NO_CHANGE[$1]="$value";; - msm-confirm-give) SERVER_CONFIRM_GIVE[$1]="$value";; - msm-confirm-give-fail-no-user) SERVER_CONFIRM_GIVE_FAIL_NO_USER[$1]="$value";; - msm-confirm-give-fail-no-item) SERVER_CONFIRM_GIVE_FAIL_NO_ITEM[$1]="$value";; - msm-confirm-xp) SERVER_CONFIRM_XP[$1]="$value";; - msm-confirm-xp-fail-no-user) SERVER_CONFIRM_XP_FAIL_NO_USER[$1]="$value";; - msm-confirm-xp-fail-invalid-amount) SERVER_CONFIRM_XP_FAIL_INVALID_AMOUNT[$1]="$value";; - esac - done < "${SERVER_CONF[$1]}" + done < "${SERVER_PATH[$1]}/$SETTINGS_SERVER_PROPERTIES" fi } @@ -2163,80 +2138,51 @@ server_load_config() { # $2: The name of the server server_init() { SERVER_NAME[$1]="$2" - SERVER_PATH[$1]="$SERVER_STORAGE_PATH/$2" - SERVER_CONF[$1]="${SERVER_PATH[$1]}/$SERVER_CONF_NAME" - SERVER_FLAG_ACTIVE[$1]="${SERVER_PATH[$1]}/active" - SERVER_BACKUP_PATH[$1]="$BACKUP_ARCHIVE_PATH/${SERVER_NAME[$1]}" - SERVER_LOG_archive_path[$1]="$LOG_ARCHIVE_PATH/${SERVER_NAME[$1]}" + SERVER_PATH[$1]="$SETTINGS_SERVER_STORAGE_PATH/$2" + + SERVER_BACKUP_PATH[$1]="$SETTINGS_BACKUP_ARCHIVE_PATH/${SERVER_NAME[$1]}" + SERVER_LOG_ARCHIVE_PATH[$1]="$SETTINGS_LOG_ARCHIVE_PATH/${SERVER_NAME[$1]}" if [[ -e "${SERVER_FLAG_ACTIVE[$1]}" ]]; then SERVER_ACTIVE[$1]="true" else SERVER_ACTIVE[$1]="false" fi + + + # Setup default values for this server's variables using default settings + # from /etc/msm.conf + local name value + + for ((i=0; i<$SERVER_SETTING_COUNT; i++)); do + name="${SERVER_SETTING_NAME[$i]}" + value="$(eval echo \$SETTINGS_DEFAULT_${name})" + + # Make relative paths absolute, assuming the server directory + # as the current directory. + if [[ "$name" =~ _PATH$ ]]; then + if [[ ! "$value" =~ ^\/ ]]; then + value="${SERVER_PATH[$1]}/$value" + fi + fi + + echo SERVER_${name}[$1]=\"${value}\" + eval SERVER_${name}[$1]=\"${value}\" + done + + # Load setting overrides from server.properties + server_load_properties "$1" - # Setup defaults - # Note: screen_name will at this stage have the {SERVER_NAME} tag in it - # which needs to be replaced. - # Invocation may also the {RAM} and {JAR} tags. - - SERVER_USER_NAME[$1]="$DEFAULT_SERVER_USER" - SERVER_SCREEN_NAME[$1]="${DEFAULT_SCREEN_NAME//\{SERVER_NAME\}/${SERVER_NAME[$1]}}" # Replace tags now, they cannot change - SERVER_WORLD_STORAGE[$1]="${SERVER_PATH[$1]}/$DEFAULT_WORLD_STORAGE_PATH" - SERVER_WORLD_STORAGE_INACTIVE[$1]="${SERVER_PATH[$1]}/$DEFAULT_WORLD_STORAGE_INACTIVE_PATH" - SERVER_LOG[$1]="${SERVER_PATH[$1]}/$DEFAULT_LOG" - SERVER_WHITELIST[$1]="${SERVER_PATH[$1]}/$DEFAULT_WHITELIST" - SERVER_BANNED_PLAYERS[$1]="${SERVER_PATH[$1]}/$DEFAULT_BANNED_PLAYERS" - SERVER_BANNED_IPS[$1]="${SERVER_PATH[$1]}/$DEFAULT_BANNED_IPS" - SERVER_OPS[$1]="${SERVER_PATH[$1]}/$DEFAULT_OPS" - SERVER_JAR[$1]="${SERVER_PATH[$1]}/$DEFAULT_JAR" - SERVER_RAM[$1]="$DEFAULT_RAM" - SERVER_INVOCATION[$1]="$DEFAULT_INVOCATION" # Don't replace tags yet, they may change - SERVER_STOP_DELAY[$1]="$DEFAULT_STOP_DELAY" - SERVER_RESTART_DELAY[$1]="$DEFAULT_RESTART_DELAY" - SERVER_STOP_MESSAGE[$1]="$DEFAULT_STOP_MESSAGE" - SERVER_STOP_ABORT[$1]="$DEFAULT_STOP_ABORT" - SERVER_RESTART_MESSAGE[$1]="$DEFAULT_RESTART_MESSAGE" - SERVER_RESTART_ABORT[$1]="$DEFAULT_RESTART_ABORT" - SERVER_WORLD_BACKUP_STARTED[$1]="$DEFAULT_WORLD_BACKUP_STARTED" - SERVER_WORLD_BACKUP_FINISHED[$1]="$DEFAULT_WORLD_BACKUP_FINISHED" - SERVER_COMPLETE_BACKUP_STARTED[$1]="$DEFAULT_COMPLETE_BACKUP_STARTED" - SERVER_COMPLETE_BACKUP_FINISHED[$1]="$DEFAULT_COMPLETE_BACKUP_FINISHED" - SERVER_COMPLETE_BACKUP_FOLLOW_SYMLINKS[$1]="$DEFAULT_COMPLETE_BACKUP_FOLLOW_SYMLINKS" - SERVER_CONFIRM_SAVE_ON[$1]="$DEFAULT_CONFIRM_SAVE_ON" - SERVER_CONFIRM_SAVE_OFF[$1]="$DEFAULT_CONFIRM_SAVE_OFF" - SERVER_CONFIRM_SAVE_ALL[$1]="$DEFAULT_CONFIRM_SAVE_ALL" - SERVER_CONFIRM_START[$1]="$DEFAULT_CONFIRM_START" - SERVER_CONFIRM_KICK[$1]="$DEFAULT_CONFIRM_KICK" - SERVER_CONFIRM_KICK_FAIL[$1]="$DEFAULT_CONFIRM_KICK_FAIL" - SERVER_CONFIRM_TIME_SET[$1]="$DEFAULT_CONFIRM_TIME_SET" - SERVER_CONFIRM_TIME_SET_FAIL[$1]="$DEFAULT_CONFIRM_TIME_SET_FAIL" - SERVER_CONFIRM_TIME_ADD[$1]="$DEFAULT_CONFIRM_TIME_ADD" - SERVER_CONFIRM_TIME_ADD_FAIL[$1]="$DEFAULT_CONFIRM_TIME_ADD_FAIL" - SERVER_CONFIRM_TOGGLEDOWNFALL[$1]="$DEFAULT_CONFIRM_TOGGLEDOWNFALL" - SERVER_CONFIRM_TOGGLEDOWNFALL_FAIL[$1]="$DEFAULT_CONFIRM_TOGGLEDOWNFALL_FAIL" - SERVER_CONFIRM_GAMEMODE[$1]="$DEFAULT_CONFIRM_GAMEMODE" - SERVER_CONFIRM_GAMEMODE_FAIL_NO_USER[$1]="$DEFAULT_CONFIRM_GAMEMODE_FAIL_NO_USER" - SERVER_CONFIRM_GAMEMODE_FAIL_NO_CHANGE[$1]="$DEFAULT_CONFIRM_GAMEMODE_FAIL_NO_CHANGE" - SERVER_CONFIRM_GIVE[$1]="$DEFAULT_CONFIRM_GIVE" - SERVER_CONFIRM_GIVE_FAIL_NO_USER[$1]="$DEFAULT_CONFIRM_GIVE_FAIL_NO_USER" - SERVER_CONFIRM_GIVE_FAIL_NO_ITEM[$1]="$DEFAULT_CONFIRM_GIVE_FAIL_NO_ITEM" - SERVER_CONFIRM_XP[$1]="$DEFAULT_CONFIRM_XP" - SERVER_CONFIRM_XP_FAIL_NO_USER[$1]="$DEFAULT_CONFIRM_XP_FAIL_NO_USER" - SERVER_CONFIRM_XP_FAIL_INVALID_AMOUNT[$1]="$DEFAULT_CONFIRM_XP_FAIL_INVALID_AMOUNT" - - - # Load config overrides from server config file if present - server_load_config "$1" - + # Perform tag replacements on specific variables + SERVER_SCREEN_NAME[$1]="${SERVER_SCREEN_NAME[$1]//\{SERVER_NAME\}/${SERVER_NAME[$1]}}" # Replace tags now, they cannot change # Replace tags in delay messages - SERVER_STOP_MESSAGE[$1]="${SERVER_STOP_MESSAGE[$1]//\{DELAY\}/${SERVER_STOP_DELAY[$1]}}" - SERVER_RESTART_MESSAGE[$1]="${SERVER_RESTART_MESSAGE[$1]//\{DELAY\}/${SERVER_RESTART_DELAY[$1]}}" + SERVER_MESSAGE_STOP[$1]="${SERVER_MESSAGE_STOP[$1]//\{DELAY\}/${SERVER_STOP_DELAY[$1]}}" + SERVER_MESSAGE_RESTART[$1]="${SERVER_MESSAGE_RESTART[$1]//\{DELAY\}/${SERVER_RESTART_DELAY[$1]}}" # Replace tags in server invocation SERVER_INVOCATION[$1]="${SERVER_INVOCATION[$1]//\{RAM\}/${SERVER_RAM[$1]}}" - SERVER_INVOCATION[$1]="${SERVER_INVOCATION[$1]//\{JAR\}/${SERVER_JAR[$1]}}" + SERVER_INVOCATION[$1]="${SERVER_INVOCATION[$1]//\{JAR\}/${SERVER_JAR_PATH[$1]}}" # Load worlds if there is a world storage directory present @@ -2249,7 +2195,7 @@ server_init() { # Record the index at which worlds for this server start SERVER_WORLD_OFFSET[$1]="$id" - if [[ -d "${SERVER_WORLD_STORAGE[$1]}" ]]; then + if [[ -d "${SERVER_WORLD_STORAGE_PATH[$1]}" ]]; then # Load active worlds while IFS= read -r -d $'\0' path; do local name="$(basename "$path")" @@ -2264,10 +2210,10 @@ server_init() { id="$(($id+1))" num_worlds="$id" - done < <(find "${SERVER_WORLD_STORAGE[$1]}" -mindepth 1 -maxdepth 1 -type d -print0) + done < <(find "${SERVER_WORLD_STORAGE_PATH[$1]}" -mindepth 1 -maxdepth 1 -type d -print0) fi - if [[ -d "${SERVER_WORLD_STORAGE_INACTIVE[$1]}" ]]; then + if [[ -d "${SERVER_WORLD_STORAGE_INACTIVE_PATH[$1]}" ]]; then # Load inactive worlds while IFS= read -r -d $'\0' path; do local name="$(basename "$path")" @@ -2282,99 +2228,146 @@ server_init() { id="$(($id+1))" num_worlds="$id" - done < <(find "${SERVER_WORLD_STORAGE_INACTIVE[$1]}" -mindepth 1 -maxdepth 1 -type d -print0) + done < <(find "${SERVER_WORLD_STORAGE_INACTIVE_PATH[$1]}" -mindepth 1 -maxdepth 1 -type d -print0) fi # Record the number of worlds this server has SERVER_NUM_WORLDS[$1]="$(( $id - ${SERVER_WORLD_OFFSET[$1]} ))" } -# Asserts that a variable has been set in the config file -# $1: The name of the variable to test -assert_is_set_in_config() { - [[ ! ${!1} && ${!1-_} ]] && { - error_exit CONF_ERROR "Have you recently upgraded? \"$1\" is a new required setting, and must be set in $CONF. See https://raw.github.com/marcuswhybrow/minecraft-server-manager/${VERSION}/msm.conf and look for the line starting with \"$1\". Add this line to your settings. Sorry about this... A better sollution for upgrading is being worked on." - } +# Registers a setting that can be defined in /etc/msm.conf +# $1: Setting name to register +# $2: Optionally a default value for this setting +register_setting() { + # Create the default version of the variable + eval SETTINGS_$1=\"$2\" + + SETTING_NAME[$SETTING_COUNT]="$1" + SETTING_COUNT=$(( $SETTING_COUNT + 1 )) } -# Ensures all non-optional settings have been set -init_ensure_settings() { - assert_is_set_in_config USERNAME - assert_is_set_in_config SERVER_STORAGE_PATH - assert_is_set_in_config JAR_STORAGE_PATH - assert_is_set_in_config RAMDISK_STORAGE_PATH - - assert_is_set_in_config WORLD_ARCHIVE_PATH - assert_is_set_in_config LOG_ARCHIVE_PATH - assert_is_set_in_config BACKUP_ARCHIVE_PATH - - assert_is_set_in_config DEFAULT_SERVER_USER - assert_is_set_in_config DEFAULT_SCREEN_NAME - assert_is_set_in_config DEFAULT_WORLD_STORAGE_PATH - assert_is_set_in_config DEFAULT_WORLD_STORAGE_INACTIVE_PATH - assert_is_set_in_config DEFAULT_COMPLETE_BACKUP_FOLLOW_SYMLINKS - - assert_is_set_in_config DEFAULT_LOG - assert_is_set_in_config DEFAULT_PROPERTIES - assert_is_set_in_config DEFAULT_WHITELIST - assert_is_set_in_config DEFAULT_BANNED_PLAYERS - assert_is_set_in_config DEFAULT_BANNED_IPS - assert_is_set_in_config DEFAULT_OPS +# Registers a setting that can be defined for each server +# $1: Server setting name to register +# $2: Optionally a default value +register_server_setting() { + register_setting "DEFAULT_$1" "$2" - assert_is_set_in_config DEFAULT_JAR - assert_is_set_in_config DEFAULT_RAM - assert_is_set_in_config DEFAULT_INVOCATION + SERVER_SETTING_NAME[$SERVER_SETTING_COUNT]="$1" + SERVER_SETTING_COUNT=$(( $SERVER_SETTING_COUNT + 1 )) +} + +# Register possible settings +register_settings() { + register_setting USERNAME "minecraft" + register_setting SERVER_STORAGE_PATH "/opt/msm/servers" + register_setting JAR_STORAGE_PATH "/opt/msm/jars" + register_setting RAMDISK_STORAGE_PATH "/dev/shm/msm" + + register_setting WORLD_ARCHIVE_PATH "/opt/msm/archives/worlds" + register_setting LOG_ARCHIVE_PATH "/opt/msm/archives/logs" + register_setting BACKUP_ARCHIVE_PATH "/opt/msm/archives/backups" + + register_setting JARGROUP_TARGET "target.txt" + register_setting JARGROUP_DOWNLOAD_DIR "downloads" + register_setting SERVER_PROPERTIES "server.properties" - assert_is_set_in_config DEFAULT_STOP_DELAY - assert_is_set_in_config DEFAULT_RESTART_DELAY - assert_is_set_in_config DEFAULT_STOP_MESSAGE - assert_is_set_in_config DEFAULT_STOP_ABORT - assert_is_set_in_config DEFAULT_RESTART_MESSAGE - assert_is_set_in_config DEFAULT_RESTART_ABORT - assert_is_set_in_config DEFAULT_WORLD_BACKUP_STARTED - assert_is_set_in_config DEFAULT_WORLD_BACKUP_FINISHED - assert_is_set_in_config DEFAULT_COMPLETE_BACKUP_STARTED - assert_is_set_in_config DEFAULT_COMPLETE_BACKUP_FINISHED - assert_is_set_in_config DEFAULT_CONFIRM_SAVE_ON - assert_is_set_in_config DEFAULT_CONFIRM_SAVE_OFF - assert_is_set_in_config DEFAULT_CONFIRM_SAVE_ALL - assert_is_set_in_config DEFAULT_CONFIRM_START - assert_is_set_in_config DEFAULT_CONFIRM_KICK - assert_is_set_in_config DEFAULT_CONFIRM_KICK_FAIL - assert_is_set_in_config DEFAULT_CONFIRM_TIME_SET - assert_is_set_in_config DEFAULT_CONFIRM_TIME_SET_FAIL - assert_is_set_in_config DEFAULT_CONFIRM_TIME_ADD - assert_is_set_in_config DEFAULT_CONFIRM_TIME_ADD_FAIL - assert_is_set_in_config DEFAULT_CONFIRM_TOGGLEDOWNFALL - assert_is_set_in_config DEFAULT_CONFIRM_TOGGLEDOWNFALL_FAIL - assert_is_set_in_config DEFAULT_CONFIRM_GAMEMODE - assert_is_set_in_config DEFAULT_CONFIRM_GAMEMODE_FAIL_NO_USER - assert_is_set_in_config DEFAULT_CONFIRM_GAMEMODE_FAIL_NO_CHANGE - assert_is_set_in_config DEFAULT_CONFIRM_GIVE - assert_is_set_in_config DEFAULT_CONFIRM_GIVE_FAIL_NO_USER - assert_is_set_in_config DEFAULT_CONFIRM_GIVE_FAIL_NO_ITEM - assert_is_set_in_config DEFAULT_CONFIRM_XP - assert_is_set_in_config DEFAULT_CONFIRM_XP_FAIL_NO_USER - assert_is_set_in_config DEFAULT_CONFIRM_XP_FAIL_INVALID_AMOUNT + register_server_setting USERNAME "minecraft" + register_server_setting SCREEN_NAME "msm-{SERVER_NAME}" + + register_server_setting WORLD_STORAGE_PATH "worldstorage" + register_server_setting WORLD_STORAGE_INACTIVE_PATH "worldstorage_inactive" + register_server_setting LOG_PATH "server.log" + register_server_setting WHITELIST_PATH "white-list.txt" + register_server_setting BANNED_PLAYERS_PATH "banned-players.txt" + register_server_setting BANNED_IPS_PATH "banned-ips.txt" + register_server_setting OPS_PATH "ops.txt" + register_server_setting JAR_PATH "server.jar" + + register_server_setting FLAG_ACTIVE_PATH "active" + register_server_setting COMPLETE_BACKUP_FOLLOW_SYMLINKS "false" + + register_server_setting RAM "1024" + register_server_setting INVOCATION "java -Xms{RAM}M -Xmx{RAM}M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:+AggressiveOpts -jar {JAR} nogui" + register_server_setting STOP_DELAY "10" + register_server_setting RESTART_DELAY "10" + + register_server_setting MESSAGE_STOP "SERVER SHUTTING DOWN IN {DELAY} SECONDS!" + register_server_setting MESSAGE_STOP_ABORT "Server shut down aborted." + register_server_setting MESSAGE_RESTART "SERVER REBOOT IN {DELAY} SECONDS!" + register_server_setting MESSAGE_RESTART_ABORT "Server reboot aborted." + register_server_setting MESSAGE_WORLD_BACKUP_STARTED "Backing up world." + register_server_setting MESSAGE_WORLD_BACKUP_FINISHED "Backup complete." + register_server_setting MESSAGE_COMPLETE_BACKUP_STARTED "Backing up entire server." + register_server_setting MESSAGE_COMPLETE_BACKUP_FINISHED "Backup complete." + + register_server_setting CONFIRM_SAVE_ON "CONSOLE: Enabling level saving.." + register_server_setting CONFIRM_SAVE_OFF "CONSOLE: Disabling level saving.." + register_server_setting CONFIRM_SAVE_ALL "CONSOLE: Save complete." + register_server_setting CONFIRM_START "Done" + register_server_setting CONFIRM_KICK "CONSOLE: Kicking " + register_server_setting CONFIRM_KICK_FAIL "Can't find user " + register_server_setting CONFIRM_TIME_SET "CONSOLE: Set time to" + register_server_setting CONFIRM_TIME_SET_FAIL "Unable to convert time value" + register_server_setting CONFIRM_TIME_ADD "CONSOLE: Added .+ to time" + register_server_setting CONFIRM_TIME_ADD_FAIL "Unable to convert time value" + register_server_setting CONFIRM_TOGGLEDOWNFALL "CONSOLE: Toggling downfall on|off for world" + register_server_setting CONFIRM_TOGGLEDOWNFALL_FAIL ".\[31m;1mNo world exists with the name" + register_server_setting CONFIRM_GAMEMODE "CONSOLE: Setting .+ to game mode (1|0)" + register_server_setting CONFIRM_GAMEMODE_FAIL_NO_USER "Can't find user .+" + register_server_setting CONFIRM_GAMEMODE_FAIL_NO_CHANGE ".+ already has game mode (1|0)" + register_server_setting CONFIRM_GIVE "CONSOLE: Giving .+ some .+ (.+)" + register_server_setting CONFIRM_GIVE_FAIL_NO_USER "Can't find user .+" + register_server_setting CONFIRM_GIVE_FAIL_NO_ITEM "There's no item called .+" + register_server_setting CONFIRM_XP "CONSOLE: Giving .+ exp to .+" + register_server_setting CONFIRM_XP_FAIL_NO_USER "Can't find user .+" + register_server_setting CONFIRM_XP_FAIL_INVALID_AMOUNT "Invalid exp count: .+" +} + +load_conf() { + if [[ -f "$CONF" ]]; then + while read line; do + # ignore comment lines + if [[ "$line" =~ ^# ]]; then + continue + fi + + # if not empty, get the name and value of the setting + if [[ "$line" =~ ^(.*)=(.*)$ ]]; then + name="${BASH_REMATCH[1]}" + value="${BASH_REMATCH[2]}" + + # If the value is wrapped in double or single quotations + # remove them from the value. + if [[ "$value" =~ ^\".*\"$ ]] || [[ "$value" =~ ^\'.*\'$ ]]; then + value="${value:1:${#value}-2}" + fi + + name="$(echo "$name" | tr '[\-a-z]' '[\_A-Z]')" + + # Create variables + if [[ "$name" =~ ^[\_A-Z0-9]+$ ]]; then + eval SETTINGS_${name}=\"$value\" + fi + fi + done < "$CONF" + fi } init() { - # Sourcing $CONF will override the previous defaults, with new values - source "$CONF" - - init_ensure_settings + register_settings + load_conf num_worlds=0 num_servers=0 - if [ -d "$SERVER_STORAGE_PATH" ]; then + if [ -d "$SETTINGS_SERVER_STORAGE_PATH" ]; then local id=0 while IFS= read -r -d $'\0' path; do local name="$(basename "$path")" server_init "$id" "$name" id="$(($id+1))" num_servers="$id" - done < <(find "$SERVER_STORAGE_PATH" -mindepth 1 -maxdepth 1 -type d -print0) + done < <(find "$SETTINGS_SERVER_STORAGE_PATH" -mindepth 1 -maxdepth 1 -type d -print0) fi } @@ -2387,7 +2380,7 @@ interrupt() { echo -e "\nInterrupted..." exit_message="true" fi - server_eval "$i" "say ${SERVER_STOP_ABORT[$i]}" + server_eval "$i" "say ${SERVER_MESSAGE_STOP_ABORT[$i]}" echo "Server \"${SERVER_NAME[$i]}\" shutdown was aborted." fi @@ -2396,15 +2389,13 @@ interrupt() { echo -e "\nInterrupted..." exit_message="true" fi - server_eval "$i" "say ${SERVER_RESTART_ABORT[$i]}" + server_eval "$i" "say ${SERVER_MESSAGE_RESTART_ABORT[$i]}" echo "Server \"${SERVER_NAME[$i]}\" restart was aborted." fi done exit } -COMMAND_COUNT=0 - # Adds a command to the list, allowing it to be called from the command line. # $1: The command signature, a coded string describing the structure of the # command. @@ -2549,7 +2540,7 @@ call_command() { sid="server:all" else if is_valid_name "$specified_name"; then - if [ -d "$SERVER_STORAGE_PATH/$specified_name" ]; then + if [ -d "$SETTINGS_SERVER_STORAGE_PATH/$specified_name" ]; then sid="$(server_get_id "$specified_name")" fi fi @@ -2585,7 +2576,7 @@ call_command() { if [[ "$sid" -ge "0" ]]; then if is_valid_name "$specified_name"; then - if [ -d "${SERVER_WORLD_STORAGE[$sid]}/$specified_name" ] || [ -d "${SERVER_WORLD_STORAGE_INACTIVE[$sid]}/$specified_name" ]; then + if [ -d "${SERVER_WORLD_STORAGE_PATH[$sid]}/$specified_name" ] || [ -d "${SERVER_WORLD_STORAGE_INACTIVE_PATH2[$sid]}/$specified_name" ]; then wid="$(server_world_get_id "$sid" "$specified_name")" fi fi @@ -2715,6 +2706,7 @@ main() { register_command "restart" "command_restart" register_command "restart now" "command_restart_now" register_command "version" "command_version" + register_command "config" "command_config" register_command "server list" "command_server_list" register_command "server create " "command_server_create" register_command "server delete " "command_server_delete" @@ -2773,7 +2765,8 @@ main() { register_command " cmd " "command_server_cmd" register_command " cmdlog " "command_server_cmdlog" register_command " console" "command_server_console" - register_command " config " "command_set_config" + register_command " config" "command_server_config" + register_command " config " "command_server_config" # This function call matches the user input to a registered command # signature, and then calls that commands handler function with positional # arguments containing any variable strings. diff --git a/msm.conf b/msm.conf index 4e6887c..4cc4937 100644 --- a/msm.conf +++ b/msm.conf @@ -1,5 +1,4 @@ -#!/bin/bash - +# # Minecraft Server Manager Configuration File # =========================================== # @@ -64,6 +63,10 @@ BACKUP_ARCHIVE_PATH="/opt/msm/archives/backups" # They are also the default values used when a new server is created, without # specifying any arguments. +# Any settings in the Server Defaults sections ending in PATH are relative +# to the server directory. That is unless an absolute path is given (one +# starting with a forward slash '/'.) + # User which stars the server, and interacts with it DEFAULT_SERVER_USER="minecraft" @@ -90,15 +93,15 @@ DEFAULT_COMPLETE_BACKUP_FOLLOW_SYMLINKS="false" # The location of standard Minecraft server files, relative to the # server directory -DEFAULT_LOG="server.log" -DEFAULT_PROPERTIES="server.properties" -DEFAULT_WHITELIST="white-list.txt" -DEFAULT_BANNED_PLAYERS="banned-players.txt" -DEFAULT_BANNED_IPS="banned-ips.txt" -DEFAULT_OPS="ops.txt" +DEFAULT_LOG_PATH="server.log" +DEFAULT_PROPERTIES_PATH="server.properties" +DEFAULT_WHITELIST_PATH="white-list.txt" +DEFAULT_BANNED_PLAYERS_PATH="banned-players.txt" +DEFAULT_BANNED_IPS_PATH="banned-ips.txt" +DEFAULT_OPS_PATH="ops.txt" # The location of the jar file to execute, relative to the server directory -DEFAULT_JAR="server.jar" +DEFAULT_JAR_PATH="server.jar" # The amount of memory to dedicate to a server (in MB) DEFAULT_RAM="1024" @@ -126,36 +129,36 @@ DEFAULT_RESTART_DELAY=10 # The default message to send to players on a server which is about to be # shut down. You may use the tag "{DELAY}" to specify the time delay # before shutdown: -DEFAULT_STOP_MESSAGE="SERVER SHUTTING DOWN IN {DELAY} SECONDS!" +DEFAULT_MESSAGE_STOP="SERVER SHUTTING DOWN IN {DELAY} SECONDS!" # The default message sent to players on a server which was in the process of # shutting down, but was aborted by an admin probably pressing Ctrl+C. -DEFAULT_STOP_ABORT="Server shut down aborted." +DEFAULT_MESSAGE_STOP_ABORT="Server shut down aborted." # The default message sent to players on a server which is about to be # restarted. You may use the tag "{DELAY}" to specify the time delay before # the server restarts: -DEFAULT_RESTART_MESSAGE="SERVER REBOOT IN {DELAY} SECONDS!" +DEFAULT_MESSAGE_RESTART="SERVER REBOOT IN {DELAY} SECONDS!" # The default message sent to players on a server which was in the process of # restarting, but was aborted by an admin probably pressing Ctrl+C. -DEFAULT_RESTART_ABORT="Server reboot aborted." +DEFAULT_MESSAGE_RESTART_ABORT="Server reboot aborted." # The default message to send to players when a server begins backing up # its worlds: -DEFAULT_WORLD_BACKUP_STARTED="Backing up world." +DEFAULT_MESSAGE_WORLD_BACKUP_STARTED="Backing up world." # The default message to send to players when a server has finished backing # up its worlds: -DEFAULT_WORLD_BACKUP_FINISHED="Backup complete." +DEFAULT_MESSAGE_WORLD_BACKUP_FINISHED="Backup complete." # The default message to send to players when a server begins backing up the # entire server directory: -DEFAULT_COMPLETE_BACKUP_STARTED="Backing up entire server." +DEFAULT_MESSAGE_COMPLETE_BACKUP_STARTED="Backing up entire server." # The default message to send to players when a serer finishes backing up the # entire server directory: -DEFAULT_COMPLETE_BACKUP_FINISHED="Backup complete." +DEFAULT_MESSAGE_COMPLETE_BACKUP_FINISHED="Backup complete." # The message once logged confirms the "save-on" command has finished