mirror of
https://github.com/msmhq/msm.git
synced 2024-08-30 18:12:35 +00:00
2078 lines
62 KiB
Bash
Executable File
2078 lines
62 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
### BEGIN INIT INFO
|
||
# Provides: msm
|
||
# 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:
|
||
# Description:
|
||
### END INIT INFO
|
||
|
||
|
||
# See http://www.debian.org/doc/debian-policy/ch-opersys.html#s-sysvinit for
|
||
# more information on debain init.d scripts, which may help you understand
|
||
# this script.
|
||
|
||
|
||
### The configuration file
|
||
CONFIG="/etc/msm.conf"
|
||
|
||
|
||
### Config variables the user should 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 flag which indicates the world should be put in RAM
|
||
declare -r WORLD_FLAG_INRAM="inram"
|
||
# The flag which indicates the server is active
|
||
declare -r SERVER_FLAG_ACTIVE="active"
|
||
|
||
# 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} \[.*\]"
|
||
|
||
|
||
### Script State Variables
|
||
|
||
# "true" whilst the script is counting down a delay to stop the server
|
||
declare STOP_COUNTDOWN
|
||
|
||
# "true" whilst the script is counting down a delay to restart the server
|
||
declare RESTART_COUNTDOWN
|
||
|
||
|
||
### Utility Functions
|
||
|
||
# Executes the command "$2" as user "$1"
|
||
# $1: The user to execute the command as
|
||
# $2: The command to execute
|
||
as_user() {
|
||
local user="$(whoami)"
|
||
if [ "$user" == "$1" ]; then
|
||
bash -c "$2"
|
||
else
|
||
if [ "$user" == "root" ]; then
|
||
su - $1 -s /bin/bash -c "$2"
|
||
else
|
||
echoerr "This command must be executed as the user \"$1\" or \"root\"."
|
||
exit 1
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# Executes the command "$1" as SERVER_USER but returns stderr instead
|
||
as_user_stderr() {
|
||
as_user "$@" > /dev/null 2>&1
|
||
}
|
||
|
||
# Echo to stderr
|
||
echoerr() {
|
||
echo "$@" 1>&2
|
||
}
|
||
|
||
# Determines whether "$1" is a valid name for a server or jar group directory
|
||
# It must only contain upper or lower case letters, digits, dashes or
|
||
# underscores.
|
||
# It must also not be one of a list of reserved names.
|
||
is_valid_name() {
|
||
local valid="^[a-zA-Z0-9\_\-]+$"
|
||
local invalid="^server|jargroup|start|stop|restart|all$"
|
||
|
||
if [[ $1 =~ $valid ]]; then
|
||
if [[ $1 =~ $invalid ]]; then
|
||
echoerr "Invalid name \"$1\": A name may not be any of the following reserved worlds \"start\", \"stop\", \"restart\", \"server\", \"jargroup\" or \"all\"."
|
||
return 1
|
||
else
|
||
return 0
|
||
fi
|
||
else
|
||
echoerr "Invalid name \"$1\": A name may only contain letters, numbers, dashes and unscores."
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Gets the latest jar from a jar group, based upon the date and time encoded
|
||
# in the file name.
|
||
# $1: The directory to search
|
||
get_latest_file() {
|
||
local best_time=0
|
||
local best_file=""
|
||
|
||
while IFS= read -r -d $'\0' file; do
|
||
# Remove the path, leaving just the file name
|
||
local date_time=$(basename "$file" | awk -F '-' '{print $1 "-" $2 "-" $3 " " $4 ":" $5 ":" $6}')
|
||
|
||
# Get the time in seconds since 1970 from file name
|
||
local seconds=$(date -d "$date_time" "+%s" 2> /dev/null)
|
||
|
||
# If that is newer than the current best, override variables
|
||
if [[ $seconds > $best_time ]]; then
|
||
best_time=$seconds
|
||
best_file=$file
|
||
fi
|
||
done < <(find "$1" -maxdepth 1 -type f -print0)
|
||
|
||
echo $best_file
|
||
}
|
||
|
||
# Returns the current time as a UNIX timestamp (in seconds since 1970)
|
||
now() {
|
||
date +%s
|
||
}
|
||
|
||
|
||
### Log Utility Functions
|
||
|
||
# Gets the 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
|
||
}
|
||
|
||
|
||
### World Utility Functions
|
||
|
||
# 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 '$WORLD_FLAG_INRAM' \"${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 '$WORLD_FLAG_INRAM' \"${world_ramdisk_path[$1]}/\" \"${world_path[$1]}\""
|
||
}
|
||
|
||
# Toggles a worlds ramdisk state
|
||
# $1: The ID of the world
|
||
world_toggle_ramdisk_state() {
|
||
if [ -e ${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]}\""
|
||
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]}\""
|
||
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]}\""
|
||
echo "Done."
|
||
|
||
echo -n "Copying world to RAM... "
|
||
world_to_ram $1
|
||
echo "Done."
|
||
fi
|
||
echo "Changes will only take effect after server is restarted."
|
||
}
|
||
|
||
# Backs up a world
|
||
# $1: The ID of the world
|
||
world_backup() {
|
||
echo -n "Backing up world \"${world_name[$1]}\"... "
|
||
|
||
file_name="$(date "+%F-%H-%M-%S").zip"
|
||
local server_id=${world_server_id[$1]}
|
||
as_user ${server_user_name[$server_id]} "mkdir -p \"${world_backup_path[$1]}\" && cd \"${server_world_storage[$server_id]}\" && zip -rq \"${world_backup_path[$1]}/${file_name}\" \"${world_name[$1]}\""
|
||
|
||
echo "Done."
|
||
}
|
||
|
||
|
||
### Server Utility Functions
|
||
|
||
# Returns the ID for a server.
|
||
# An ID is given to a server when loaded into memory, and can be used to lookup
|
||
# config information for that server
|
||
# $1: The name of the server
|
||
server_get_id() {
|
||
local i=0
|
||
while [[ $i -lt $num_servers ]]; do
|
||
if [[ "${server_name[$i]}" == "$1" ]]; then
|
||
echo "$i"
|
||
return 0
|
||
fi
|
||
|
||
i=$(( $i + 1 ))
|
||
done
|
||
|
||
return 1
|
||
}
|
||
|
||
# Returns the ID of a server's world.
|
||
# $1: The ID of the server
|
||
# $2: The name of the world
|
||
server_world_get_id() {
|
||
local i=${server_world_offset[$1]}
|
||
local max=$(( $i + ${server_num_worlds[$1]} ))
|
||
|
||
# For each of the servers worlds:
|
||
while [[ $i -lt $max ]]; do
|
||
if [[ "${world_name[$i]}" == "$2" ]]; then
|
||
echo $i
|
||
return 0
|
||
fi
|
||
|
||
i=$(( $i + 1 ))
|
||
done
|
||
|
||
return 1
|
||
}
|
||
|
||
# Returns 0 if the server $1 is running and 1 if not
|
||
# $1: The ID of the server
|
||
server_is_running() {
|
||
if ps ax | grep -v grep | grep "${server_screen_name[$1]} ${server_invocation[$1]}" > /dev/null
|
||
then
|
||
return 0
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Creates symbolic links in the server directory (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() {
|
||
echo -n "Maintaining world symbolic links... "
|
||
local i=${server_world_offset[$1]}
|
||
local max=$(( $i + ${server_num_worlds[$1]} ))
|
||
local output="false"
|
||
|
||
while [[ $i -lt $max ]]; 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 "${world_link[$i]}" || ! -a "${world_link[$i]}" ]]; then
|
||
# If there is a symbolic link in the server direcotry to this world,
|
||
# or there is not a directory in the server directory containing 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 "${world_link[$i]}")
|
||
|
||
if ${world_inram[$i]}; then
|
||
# If this world is marked as loaded into RAM
|
||
|
||
if [ "${link_target}" != "${world_ramdisk_path[$i]}" ]; then
|
||
# 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]}\""
|
||
|
||
# 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]}\""
|
||
fi
|
||
else
|
||
# Otherwise the world is not loaded into RAM, and is just on disk
|
||
|
||
if [ "${link_target}" != "${world_path[$i]}" ]; then
|
||
# 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]}\""
|
||
|
||
# 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]}\""
|
||
fi
|
||
fi
|
||
else
|
||
echoerr -en "\n Error: Could not create link for world \"${world_name[$i]}\". The file \"${world_link[$i]}\" already exists, and should not be overwritten automatically. Either remove this file, or rename \"${world_name[$i]}\"."
|
||
output="true"
|
||
fi
|
||
|
||
i=$(( $i + 1 ))
|
||
done
|
||
|
||
if [[ $output == "true" ]]; then
|
||
echo -e "\nDone."
|
||
else
|
||
echo "Done."
|
||
fi
|
||
}
|
||
|
||
# Moves a servers worlds into RAM
|
||
# $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
|
||
echo -n "Synchronising flagged worlds on disk to RAM... "
|
||
local i=${server_world_offset[$1]}
|
||
local max=$(( $i + ${server_num_worlds[$1]} ))
|
||
|
||
# For each of the servers worlds:
|
||
while [[ $i -lt $max ]]; do
|
||
if ${world_inram[$i]} && [ -L ${world_link[$i]} ]; then
|
||
world_to_ram $i
|
||
fi
|
||
|
||
i=$(( $i + 1 ))
|
||
done
|
||
echo "Done."
|
||
fi
|
||
}
|
||
|
||
# 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
|
||
echo -n "Synchronising worlds in RAM to disk... "
|
||
local i=${server_world_offset[$1]}
|
||
local max=$(( $i + ${server_num_worlds[$1]} ))
|
||
|
||
# For each of the servers worlds:
|
||
while [[ $i -lt $max ]]; do
|
||
if [ -e ${world_ramdisk_path[$i]} ]; then
|
||
world_to_disk $i
|
||
fi
|
||
|
||
i=$(( $i + 1 ))
|
||
done
|
||
echo "Done."
|
||
fi
|
||
}
|
||
|
||
# Watches a server's log for a specific line
|
||
# $1: The ID for the server
|
||
# $2: A UNIX timestamp (seconds since 1970) which the $3 line must be after
|
||
# $3->: The line or lines in the log to wait for
|
||
# 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]}"
|
||
|
||
while read line; do
|
||
line_time=$(log_line_get_time "$line")
|
||
|
||
# If the entry is old enough
|
||
if [[ $line_time -ge $2 ]]; then
|
||
for search_line in "${@:3}"; do
|
||
local regex="${LOG_REGEX} ${search_line}"
|
||
# and matches the regular expression
|
||
if [[ $line =~ $regex ]]; then
|
||
echo $line
|
||
return 0
|
||
fi
|
||
done
|
||
fi
|
||
done < <(as_user ${server_user_name[$1]} "tail --follow --lines=100 --sleep-interval=0.1 ${server_log[$1]}")
|
||
}
|
||
|
||
# The same as server_log_get_line, but does not print the line to stdout
|
||
# when found.
|
||
server_log_wait_for_line() {
|
||
server_log_get_line "$@" > /dev/null
|
||
}
|
||
|
||
# Sends as string to a server for execution
|
||
# $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'"
|
||
}
|
||
|
||
# The same as server_eval, but also waits for a log entry before returning
|
||
# $1: The ID of the server
|
||
# $2: A line of text to enter into the server console
|
||
# $3->: The line or lines of text in the log to wait for
|
||
# stdout: The full entry found in the logs
|
||
server_eval_and_get_line() {
|
||
time_now=$(now)
|
||
server_eval $1 "$2"
|
||
server_log_get_line $1 "$time_now" "${@:3}"
|
||
}
|
||
|
||
# The same as server_eval_and_get_line, but does not print anything to stdout
|
||
server_eval_and_wait() {
|
||
server_eval_and_get_line "$@" > /dev/null
|
||
}
|
||
|
||
# Gets the process ID for a server if running, otherwise it outputs nothing
|
||
# $1: The ID of the server
|
||
server_pid() {
|
||
ps ax | grep -v grep | grep "${server_screen_name[$1]} ${server_invocation[$1]}" | awk '{print $1}'
|
||
}
|
||
|
||
# Waits for a server to stop by polling 10 times a second
|
||
# This approach is fairyl intensive, so only use when you are expecting the
|
||
# server to stop soon
|
||
# $1: The ID of the server to wait for
|
||
server_wait_for_stop() {
|
||
local pid=$(server_pid $1)
|
||
|
||
# if the process is still running, wait for it to stop
|
||
if [ ! -z $pid ]; then
|
||
while ps -p $pid > /dev/null; do
|
||
sleep 0.1
|
||
done
|
||
fi
|
||
}
|
||
|
||
# Sets a server's active/inactive state
|
||
# $1: The ID of the server
|
||
# $2: A string containing "active" or "inactive"
|
||
server_set_active() {
|
||
case "$2" in
|
||
active)
|
||
as_user ${server_user_name[$1]} "touch ${server_flag_active[$1]}"
|
||
server_active[$1]="true"
|
||
;;
|
||
inactive)
|
||
as_user ${server_user_name[$1]} "rm -f ${server_flag_active[$1]}"
|
||
server_active[$1]="false"
|
||
;;
|
||
*)
|
||
return 1
|
||
;;
|
||
esac
|
||
}
|
||
|
||
|
||
### Jar Group Functions
|
||
|
||
# Lists the jar files grouped by jar groups.
|
||
jargroup_list() {
|
||
for group in $(ls -1 "$JAR_STORAGE_PATH"); do
|
||
echo "${group}:"
|
||
for jar in $(ls -1r $JAR_STORAGE_PATH/$group); do
|
||
if [[ $jar =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}- ]]; then
|
||
echo " $jar"
|
||
fi
|
||
done
|
||
done
|
||
}
|
||
|
||
# Creates a new jargroup
|
||
# $1: The name for the jargroup
|
||
jargroup_create() {
|
||
if is_valid_name "$1"; then
|
||
if [[ ! -e "$JAR_STORAGE_PATH/$1" ]]; then
|
||
printf "Creating jar group... "
|
||
|
||
local error=$(as_user_stderr "$USERNAME" "mkdir -p '$JAR_STORAGE_PATH/$1'")
|
||
if [[ "$error" != "" ]]; then
|
||
echo "Failed."
|
||
echo "Reason: $error"
|
||
return 1
|
||
fi
|
||
|
||
error=$(as_user "$USERNAME" "echo \"$2\" > '$JAR_STORAGE_PATH/$1/$JARGROUP_TARGET'")
|
||
if [[ "$error" != "" ]]; then
|
||
echo "Failed."
|
||
echo "Reason: $error"
|
||
return 1
|
||
fi
|
||
|
||
echo "Done."
|
||
|
||
# Download the latest version now
|
||
jargroup_getlatest "$1"
|
||
else
|
||
echo "A jar group with that name already exists."
|
||
return 1
|
||
fi
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Downloads the latest version for a jargroup, using the target URL for that
|
||
# group. Saves the download with the date and time encoded in the start of the
|
||
# file name, in the jar group directory in question. Removes the file if there
|
||
# is no difference between it and the current version.
|
||
# $1: The jargroup name to download the latest version for
|
||
jargroup_getlatest() {
|
||
if is_valid_name "$1"; then
|
||
if [[ -e "$JAR_STORAGE_PATH/$1" ]]; then
|
||
if [[ -e "$JAR_STORAGE_PATH/$1/$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'")
|
||
if [[ "$error" != "" ]]; then
|
||
echo "Failed."
|
||
echo "Reason: $error"
|
||
return 1
|
||
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'"
|
||
echo "Done."
|
||
|
||
local num_files=$(as_user "$USERNAME" "ls -1 '$JAR_STORAGE_PATH/$1/$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 new_name="$(date +%F-%H-%M-%S)-$file_name"
|
||
local most_recent_jar=$(get_latest_file "$JAR_STORAGE_PATH/$1")
|
||
|
||
|
||
if [[ ! -e "$most_recent_jar" ]] || ! diff "$most_recent_jar" "$JAR_STORAGE_PATH/$1/$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
|
||
|
||
[[ -e "$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'"
|
||
|
||
if [[ ! -z $most_recent_jar ]]; then
|
||
echo "Downloaded version was different to previous latest. Saved as \"$JAR_STORAGE_PATH/$1/$new_name\"."
|
||
else
|
||
echo "Saved as \"$JAR_STORAGE_PATH/$1/$new_name\"."
|
||
fi
|
||
else
|
||
echo "Existing version \"$JAR_STORAGE_PATH/$1/$new_name\" was already up to date."
|
||
fi
|
||
|
||
elif [[ $num_files == 0 ]]; then
|
||
# No file was downloaded
|
||
echo "Failed. No files were downloaded."
|
||
else
|
||
# Multiple files were
|
||
echo "Error. URL downloads multiple files."
|
||
fi
|
||
|
||
# Clean up the temp download folder
|
||
as_user "$USERNAME" "rm -fr '$JAR_STORAGE_PATH/$1/$JARGROUP_DOWNLOAD_DIR'"
|
||
else
|
||
echo "Target URL not found, use $0 jargroup seturl <download-url>"
|
||
return 1
|
||
fi
|
||
else
|
||
echo "There is no jar group with the name \"$1\"."
|
||
return 1
|
||
fi
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Deletes an existing jargroup
|
||
# $1: The name of the existing jargroup
|
||
jargroup_delete() {
|
||
if is_valid_name "$1"; then
|
||
if [[ -e "$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"
|
||
echo "Jar group deleted."
|
||
else
|
||
echo "Jar group was NOT deleted."
|
||
fi
|
||
else
|
||
echo "There is no jar group with the name \"$1\"."
|
||
return 1
|
||
fi
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Renames an existing jargroup
|
||
# $1: The name of the existing jargroup
|
||
# $2: The new name
|
||
jargroup_rename() {
|
||
if is_valid_name "$1"; then
|
||
if [[ -e "$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
|
||
echo "Could not be renamed, there is already a jar group with the name \"$2\"."
|
||
return 1
|
||
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'"
|
||
echo "Renamed jar group \"$1\" to \"$2\"."
|
||
fi
|
||
else
|
||
return 1
|
||
fi
|
||
else
|
||
echo "There is no jar group with the name \"$1\"."
|
||
return 1
|
||
fi
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
|
||
### Server Functions
|
||
|
||
# Echos a list of servers in the SERVER_STORAGE_PATH
|
||
server_list() {
|
||
echo "Servers:"
|
||
for server in "$SERVER_STORAGE_PATH/*"; do
|
||
echo " $(basename $server)"
|
||
done
|
||
}
|
||
|
||
# Creates a new server
|
||
# $1: The server name to create
|
||
server_create() {
|
||
if is_valid_name "$1"; then
|
||
if [[ -e "$SERVER_STORAGE_PATH/$1" ]]; then
|
||
echo "A server with that name already exists."
|
||
return 1
|
||
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'"
|
||
echo "Done."
|
||
|
||
# Now that the new server has been created, we must call init again
|
||
# to ensure it is recognised.
|
||
init
|
||
|
||
server_set_jar $(server_get_id "$1") "minecraft"
|
||
fi
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Deletes an existing server
|
||
# $2: The server name to delete
|
||
server_delete() {
|
||
if is_valid_name "$1"; then
|
||
if [[ -e "$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'"
|
||
echo "Server deleted."
|
||
else
|
||
echo "Server was NOT deleted."
|
||
fi
|
||
else
|
||
echo "There is no server with the name \"$1\"."
|
||
return 1
|
||
fi
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Renames an existing server
|
||
# $1: The server name to change
|
||
# $2: The new name for the server
|
||
server_rename() {
|
||
if is_valid_name "$1"; then
|
||
if [[ -e "$SERVER_STORAGE_PATH/$1" ]]; then
|
||
# If the server name is valid and exists
|
||
|
||
# TODO: Check that the server is not running first, return if it is
|
||
|
||
if is_valid_name "$2"; then
|
||
# If the server name is valid
|
||
if [[ -e "$SERVER_STORAGE_PATH/$2" ]]; then
|
||
# and there is not already a server with the name $2
|
||
echo "Could not be renamed, there is already a server with the name \"$2\"."
|
||
return 1
|
||
else
|
||
as_user "$USERNAME" "mv '$SERVER_STORAGE_PATH/$1' '$SERVER_STORAGE_PATH/$2'"
|
||
echo "Renamed server \"$1\" to \"$2\"."
|
||
fi
|
||
else
|
||
return 1
|
||
fi
|
||
else
|
||
echo "There is no server with the name \"$1\"."
|
||
return 1
|
||
fi
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Starts a single server
|
||
# $1: The ID of the server
|
||
server_start() {
|
||
if server_is_running $1; then
|
||
echo "Server \"${server_name[$1]}\" is already running!"
|
||
else
|
||
server_ensure_links $1
|
||
server_worlds_to_ram $1
|
||
|
||
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]}"
|
||
server_log_wait_for_line $1 "$time_now" "${server_confirm_start[$1]}"
|
||
|
||
echo "Done."
|
||
fi
|
||
}
|
||
|
||
# Sends the "save-all" command to a server
|
||
# $1: The ID of the server
|
||
server_save_all() {
|
||
if server_is_running $1; then
|
||
echo -n "Forcing save... "
|
||
|
||
# Send the "save-all" command and wait for it to finish
|
||
server_eval_and_wait $1 "save-all" "${server_confirm_save_all[$1]}"
|
||
|
||
echo "Done."
|
||
else
|
||
echo "Server \"${server_name[$1]}\" is not running."
|
||
fi
|
||
}
|
||
|
||
# Sends the "save-off" command to a server
|
||
# $1: The ID of the server
|
||
server_save_off() {
|
||
if server_is_running $1; then
|
||
echo -n "Disabling level saving... "
|
||
|
||
# Send the "save-off" command and wait for it to finish
|
||
server_eval_and_wait $1 "save-off" "${server_confirm_save_off[$1]}"
|
||
|
||
echo "Done."
|
||
|
||
# Writes any in-memory data manged by the kernel to disk
|
||
sync
|
||
else
|
||
echo "Server \"${server_name[$1]}\" is not running."
|
||
fi
|
||
}
|
||
|
||
# Sends the "save-on" command to a server
|
||
# $1: The ID of the server
|
||
server_save_on() {
|
||
if server_is_running $1; then
|
||
echo -n "Enabling level saving... "
|
||
|
||
# Send the "save-on" command and wait for it to finish
|
||
server_eval_and_wait $1 "save-on" "${server_confirm_save_on[$1]}"
|
||
|
||
echo "Done."
|
||
else
|
||
echo "Server \"${server_name[$1]}\" is not running."
|
||
fi
|
||
}
|
||
|
||
# Stops a single server after a delay
|
||
# $1: The ID of the server
|
||
server_stop() {
|
||
if server_is_running $1; then
|
||
# Change the state of the script
|
||
STOP_COUNTDOWN[$id]="true"
|
||
|
||
server_eval $id "say ${server_stop_message[$id]}"
|
||
echo "Issued the warning \"${server_stop_message[$id]}\" to players."
|
||
|
||
echo -n "Shutting down... "
|
||
|
||
for ((i=${server_stop_delay[$id]}; i>0; i--)); do
|
||
tput sc # Save cursor position
|
||
echo -n "in $i seconds."
|
||
sleep 1
|
||
|
||
tput rc # Restore cursor to position of last `sc'
|
||
tput el # Clear to end of line
|
||
done
|
||
|
||
echo -e "Now."
|
||
|
||
server_stop_now $1
|
||
else
|
||
echo "Server \"${server_name[$1]}\" is not running."
|
||
fi
|
||
}
|
||
|
||
# Stops a single server right now
|
||
# $1: The ID of the server
|
||
server_stop_now() {
|
||
if server_is_running $1; then
|
||
server_save_all $1
|
||
|
||
echo -n "Stopping the server... "
|
||
|
||
server_eval $1 "stop"
|
||
STOP_COUNTDOWN[$1]="false"
|
||
RESTART_COUNTDOWN[$1]="false"
|
||
server_wait_for_stop $1
|
||
|
||
echo "Done."
|
||
|
||
# Synchronise all worlds in RAM to disk
|
||
server_worlds_to_disk $1
|
||
else
|
||
echo "Server \"${server_name[$1]}\" is not running."
|
||
fi
|
||
}
|
||
|
||
# Restarts a single server after a delay
|
||
# $1: The ID of the server
|
||
server_restart() {
|
||
# Restarts the server if it is already running
|
||
if server_is_running $1; then
|
||
# Change the state of the script
|
||
RESTART_COUNTDOWN[$id]="true"
|
||
|
||
server_eval $id "say ${server_restart_message[$id]}"
|
||
echo "Issued the warning \"${server_restart_message[$id]}\" to players."
|
||
|
||
echo -n "Restarting... "
|
||
|
||
for ((i=${server_stop_delay[$id]}; i>0; i--)); do
|
||
tput sc # Save cursor position
|
||
echo -n "in $i seconds."
|
||
sleep 1
|
||
|
||
tput rc # Restore cursor to position of last `sc'
|
||
tput el # Clear to end of line
|
||
done
|
||
|
||
echo -e "Now."
|
||
|
||
server_stop_now $1
|
||
fi
|
||
|
||
server_start $1
|
||
}
|
||
|
||
# Restarts a single server right away
|
||
# $1: The ID of the server
|
||
server_restart_now() {
|
||
# Restarts the server if it is already running
|
||
if server_is_running $1; then
|
||
server_stop_now $1
|
||
fi
|
||
|
||
server_start $1
|
||
}
|
||
|
||
# List the worlds available for a server
|
||
# $1: The ID of the server
|
||
server_worlds_list() {
|
||
local i=${server_world_offset[$1]}
|
||
local max=$(( $i + ${server_num_worlds[$1]} ))
|
||
|
||
# For each of the servers worlds:
|
||
while [[ $i -lt $max ]]; do
|
||
if ${world_inram[$i]}; then
|
||
echo "[RAM] ${world_name[$i]}"
|
||
else
|
||
echo "[DSK] ${world_name[$i]}"
|
||
fi
|
||
|
||
i=$(( $i + 1 ))
|
||
done
|
||
}
|
||
|
||
# Backs up the worlds for a server
|
||
# $1: The ID of the server
|
||
server_worlds_backup() {
|
||
local i=${server_world_offset[$1]}
|
||
local max=$(( $i + ${server_num_worlds[$1]} ))
|
||
|
||
# For each of the servers worlds:
|
||
while [[ $i -lt $max ]]; do
|
||
world_backup $i
|
||
i=$(( $i + 1 ))
|
||
done
|
||
}
|
||
|
||
# Moves a servers log into another file, leaving the original log file empty
|
||
# $1: The ID of the server
|
||
server_log_roll() {
|
||
# Moves and Gzips the logfile, a big log file slows down the
|
||
# server A LOT (what was notch thinking?)
|
||
|
||
printf "Rolling server logs... "
|
||
|
||
if [ -e "${server_log[$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}\""
|
||
|
||
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]}"
|
||
else
|
||
echoerr "Failed."
|
||
return 1
|
||
fi
|
||
fi
|
||
|
||
echo "Done."
|
||
}
|
||
|
||
# Backups a server's directory
|
||
# $1: The ID of the server
|
||
server_backup() {
|
||
echo -n "Backing up the entire server directory... "
|
||
|
||
zip_flags="-rq"
|
||
# Add the "y" flag if symbolic links should not be followed
|
||
if [ "${server_complete_backup_follow_symlinks[$1]}" != "true" ]; then
|
||
zip_flags="${zip_flags}y"
|
||
fi
|
||
|
||
# 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]}\""
|
||
|
||
echo "Done."
|
||
}
|
||
|
||
# Sets a server's jar file
|
||
# $1: The ID of the server
|
||
# $2: The name of the jar group
|
||
# $3: Optionally, a specific jar to use.
|
||
server_set_jar() {
|
||
if [ -e "$JAR_STORAGE_PATH/$3" ]; 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")
|
||
else
|
||
# If a specific jar IS mentioned use that
|
||
local jar="$JAR_STORAGE_PATH/$2/$3"
|
||
|
||
if [[ ! -e "$jar" ]]; then
|
||
echo "There is no jar named \"$3\" in jargroup \"$2\"."
|
||
return 1
|
||
fi
|
||
fi
|
||
|
||
if [[ ! -z "$jar" ]]; then
|
||
as_user "${server_user[$1]}" "ln -sf $jar ${server_jar[$1]}"
|
||
echo "Server \"${server_name[$1]}\" is now using \"$jar\"."
|
||
fi
|
||
else
|
||
echo "There is no jargorup named \"$2\"."
|
||
fi
|
||
}
|
||
|
||
# Lists the players currently connected to a server
|
||
# $1: The ID of the server
|
||
server_connected() {
|
||
if server_is_running $1; then
|
||
local line=$(server_eval_and_get_line $1 "list" "Connected players:")
|
||
|
||
# Cuts the start off the line, and the last three (invisible)
|
||
# characters from the end.
|
||
local players=${line:46:(-3)}
|
||
|
||
if [ -z "$players" ]; then
|
||
echo "No players are connected."
|
||
else
|
||
echo "$players"
|
||
fi
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running. No users are connected."
|
||
fi
|
||
}
|
||
|
||
|
||
### Manager Functions
|
||
|
||
# Stops all running servers after a servers specified delay
|
||
# $1: String containing "stop" or "restart". Represents whether the stop is
|
||
# with a mind to stop the server, or just to restart it. And effects
|
||
# the message issued to players on a server.
|
||
manager_stop_all_servers() {
|
||
# An array of true/false for each server
|
||
local was_running
|
||
# False if no servers were running at all
|
||
local any_running="false"
|
||
|
||
# For all running servers issue the stop warning
|
||
local max_countdown=0
|
||
|
||
for ((server=0; server<${num_servers}; server++)); do
|
||
if server_is_running $server; then
|
||
any_running="true"
|
||
was_running[$server]="true"
|
||
STOP_COUNTDOWN[$server]="true"
|
||
if [[ ${server_stop_delay[$i]} > $max_countdown ]]; then
|
||
max_countdown=${server_stop_delay[$server]}
|
||
fi
|
||
|
||
# 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]}";;
|
||
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.";;
|
||
esac
|
||
|
||
case ${server_stop_delay[$server]} in
|
||
0) echo " Stopping without delay.";;
|
||
1) echo " Stopping after 1 second.";;
|
||
*) echo " Stopping after ${server_stop_delay[$server]} seconds.";;
|
||
esac
|
||
else
|
||
echo "Server \"${server_name[$server]}\" was NOT running."
|
||
was_running[$server]="false"
|
||
fi
|
||
done
|
||
|
||
if "$any_running"; then
|
||
# Wait for the maximum possible delay, stopping servers
|
||
# at the correct times
|
||
echo -n "All servers will have been issued the stop command... "
|
||
for ((tick=${max_countdown}; tick>=0; tick--)); do
|
||
tput sc # Save cursor position
|
||
|
||
if [[ $tick -le 1 ]]; then
|
||
echo -n "in $tick second."
|
||
else
|
||
echo -n "in $tick seconds."
|
||
fi
|
||
|
||
# Each second check all server, to see if its their time to
|
||
# stop. If so issue the stop command, and don't hang.
|
||
for ((server=0; server<${num_servers}; server++)); do
|
||
if server_is_running $server; then
|
||
stop_tick=$(( ${max_countdown} - ${server_stop_delay[$server]} ))
|
||
if [[ $stop_tick == $tick ]]; then
|
||
server_eval $server "stop"
|
||
STOP_COUNTDOWN[$server]="false"
|
||
fi
|
||
fi
|
||
done
|
||
|
||
if [[ $tick > 0 ]]; then
|
||
sleep 1
|
||
fi
|
||
|
||
tput rc # Restore cursor to position of last `sc'
|
||
tput el # Clear to end of line
|
||
done
|
||
|
||
# Start a new line
|
||
echo "Now."
|
||
|
||
# Finally check all servers have stopped
|
||
for ((server=0; server<${num_servers}; server++)); do
|
||
if "${was_running[$server]}"; then
|
||
echo -n "Ensuring server \"${server_name[$server]}\" has stopped... "
|
||
server_wait_for_stop $server
|
||
echo "Done."
|
||
fi
|
||
done
|
||
else
|
||
echo "No servers were running."
|
||
fi
|
||
}
|
||
|
||
# Stops all running servers without delay
|
||
manager_stop_all_servers_now() {
|
||
# An array of true/false for each server
|
||
local was_running
|
||
# False if no servers were running at all
|
||
local any_running="false"
|
||
|
||
# Stop all servers at the same time
|
||
for ((server=0; server<${num_servers}; server++)); do
|
||
if server_is_running $server; then
|
||
was_running[$server]="true"
|
||
any_running="true"
|
||
echo "Server \"${server_name[$server]}\" was running, now stopping."
|
||
server_eval $server "stop"
|
||
else
|
||
echo "Server \"${server_name[$server]}\" was NOT running."
|
||
was_running[$server]="false"
|
||
fi
|
||
done
|
||
|
||
if $any_running; then
|
||
# Ensure all the servers have stopped
|
||
for ((server=0; server<${num_servers}; server++)); do
|
||
if ${was_running[$server]}; then
|
||
echo -n "Ensuring server \"${server_name[$server]}\" has stopped... "
|
||
server_wait_for_stop $server
|
||
echo "Done."
|
||
fi
|
||
done
|
||
else
|
||
echo "No servers were running."
|
||
fi
|
||
}
|
||
|
||
|
||
### Main Functions
|
||
|
||
init() {
|
||
|
||
# These defaults can be overriden in the file specified by $CONFIG
|
||
|
||
USERNAME="minecraft"
|
||
SERVER_STORAGE_PATH="/opt/msm/servers"
|
||
JAR_STORAGE_PATH="/opt/msm/jars"
|
||
RAMDISK_STORAGE_PATH="/dev/shm/msm"
|
||
WORLD_ARCHIVE_PATH="/opt/msm/archives/worlds"
|
||
LOG_ARCHIVE_PATH="/opt/msm/archives/logs"
|
||
BACKUP_ARCHIVE_PATH="/opt/msm/archives/backups"
|
||
DEFAULT_SERVER_CONF="server.conf"
|
||
DEFAULT_SERVER_USER="minecraft"
|
||
DEFAULT_SCREEN_NAME="msm-{SERVER_NAME}"
|
||
DEFAULT_WORLD_STORAGE_PATH="worldstorage"
|
||
DEFAULT_COMPLETE_BACKUP_FOLLOW_SYMLINKS="false"
|
||
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_JAR="server.jar"
|
||
DEFAULT_RAM="1024"
|
||
DEFAULT_INVOCATION="java -Xms{RAM}M -Xmx{RAM}M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:+AggressiveOpts -jar {JAR} nogui"
|
||
DEFAULT_STOP_DELAY=10
|
||
DEFAULT_RESTART_DELAY=10
|
||
DEFAULT_STOP_MESSAGE="SERVER SHUTTING DOWN IN {DELAY} SECONDS!"
|
||
DEFAULT_STOP_ABORT="Server shut down aborted."
|
||
DEFAULT_RESTART_MESSAGE="SERVER REBOOT IN {DELAY} SECONDS!"
|
||
DEFAULT_RESTART_ABORT="Server reboot aborted."
|
||
DEFAULT_WORLD_BACKUP_STARTED="Backing up world."
|
||
DEFAULT_WORLD_BACKUP_FINISHED="Backup complete."
|
||
DEFAULT_COMPLETE_BACKUP_STARTED="Backing up entire server."
|
||
DEFAULT_COMPLETE_BACKUP_FINISHED="Backup complete."
|
||
DEFAULT_CONFIRM_SAVE_ON="CONSOLE: Enabling level saving.."
|
||
DEFAULT_CONFIRM_SAVE_OFF="CONSOLE: Disabling level saving.."
|
||
DEFAULT_CONFIRM_SAVE_ALL="CONSOLE: Save complete."
|
||
DEFAULT_CONFIRM_START="Done"
|
||
DEFAULT_CONFIRM_KICK="CONSOLE: Kicking "
|
||
DEFAULT_CONFIRM_KICK_FAIL="Can't find user "
|
||
DEFAULT_CONFIRM_TIME_SET="CONSOLE: Set time to"
|
||
DEFAULT_CONFIRM_TIME_SET_FAIL="Unable to convert time value"
|
||
DEFAULT_CONFIRM_TIME_ADD="CONSOLE: Added .+ to time"
|
||
DEFAULT_CONFIRM_TIME_ADD_FAIL="Unable to convert time value"
|
||
DEFAULT_CONFIRM_TOGGLEDOWNFALL="CONSOLE: Toggling downfall on|off for world"
|
||
DEFAULT_CONFIRM_TOGGLEDOWNFALL_FAIL=".\[31m;1mNo world exists with the name"
|
||
DEFAULT_CONFIRM_GAMEMODE="CONSOLE: Setting .+ to game mode (1|0)"
|
||
DEFAULT_CONFIRM_GAMEMODE_FAIL_NO_USER="Can't find user .+"
|
||
DEFAULT_CONFIRM_GAMEMODE_FAIL_NO_CHANGE=".+ already has game mode (1|0)"
|
||
|
||
# Sourcing $CONFIG will override the previous defaults, with new values
|
||
source $CONFIG
|
||
|
||
local i=0
|
||
local j=0
|
||
|
||
for server in $(ls -1 "$SERVER_STORAGE_PATH"); do
|
||
server_name[$i]="$server"
|
||
server_path[$i]="$SERVER_STORAGE_PATH/$server"
|
||
server_conf[$i]="${server_path[$i]}/$DEFAULT_SERVER_CONF"
|
||
server_flag_active[$i]="${server_path[$i]}/$SERVER_FLAG_ACTIVE"
|
||
server_backup_path[$i]="$BACKUP_ARCHIVE_PATH/${server_name[$i]}"
|
||
server_log_archive_path[$i]="$LOG_ARCHIVE_PATH/${server_name[$i]}"
|
||
|
||
if [[ -e "${server_flag_active[$i]}" ]]; then
|
||
server_active[$i]="true"
|
||
else
|
||
server_active[$i]="false"
|
||
fi
|
||
|
||
# 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[$i]="$DEFAULT_SERVER_USER"
|
||
server_screen_name[$i]="${DEFAULT_SCREEN_NAME//\{SERVER_NAME\}/${server_name[$i]}}" # Replace tags now, they cannot change
|
||
server_world_storage[$i]="${server_path[$i]}/$DEFAULT_WORLD_STORAGE_PATH"
|
||
server_log[$i]="${server_path[$i]}/$DEFAULT_LOG"
|
||
server_properties[$i]="${server_path[$i]}/$DEFAULT_PROPERTIES"
|
||
server_whitelist[$i]="${server_path[$i]}/$DEFAULT_WHITELIST"
|
||
server_banned_players[$i]="${server_path[$i]}/$DEFAULT_BANNED_PLAYERS"
|
||
server_banned_ips[$i]="${server_path[$i]}/$DEFAULT_BANNED_IPS"
|
||
server_ops[$i]="${server_path[$i]}/$DEFAULT_OPS"
|
||
server_jar[$i]="${server_path[$i]}/$DEFAULT_JAR"
|
||
server_ram[$i]="$DEFAULT_RAM"
|
||
server_invocation[$i]="$DEFAULT_INVOCATION" # Don't replace tags yet, they may change
|
||
server_stop_delay[$i]="$DEFAULT_STOP_DELAY"
|
||
server_restart_delay[$i]="$DEFAULT_RESTART_DELAY"
|
||
server_stop_message[$i]="$DEFAULT_STOP_MESSAGE"
|
||
server_stop_abort[$i]="$DEFAULT_STOP_ABORT"
|
||
server_restart_message[$i]="$DEFAULT_RESTART_MESSAGE"
|
||
server_restart_abort[$i]="$DEFAULT_RESTART_ABORT"
|
||
server_world_backup_started[$i]="$DEFAULT_WORLD_BACKUP_STARTED"
|
||
server_world_backup_finished[$i]="$DEFAULT_WORLD_BACKUP_FINISHED"
|
||
server_complete_backup_started[$i]="$DEFAULT_COMPLETE_BACKUP_STARTED"
|
||
server_complete_backup_finished[$i]="$DEFAULT_COMPLETE_BACKUP_FINISHED"
|
||
server_confirm_save_on[$i]="$DEFAULT_CONFIRM_SAVE_ON"
|
||
server_confirm_save_off[$i]="$DEFAULT_CONFIRM_SAVE_OFF"
|
||
server_confirm_save_all[$i]="$DEFAULT_CONFIRM_SAVE_ALL"
|
||
server_confirm_start[$i]="$DEFAULT_CONFIRM_START"
|
||
server_confirm_kick[$i]="$DEFAULT_CONFIRM_KICK"
|
||
server_confirm_kick_fail[$i]="$DEFAULT_CONFIRM_KICK_FAIL"
|
||
server_confirm_time_set[$i]="$DEFAULT_CONFIRM_TIME_SET"
|
||
server_confirm_time_set_fail[$i]="$DEFAULT_CONFIRM_TIME_SET_FAIL"
|
||
server_confirm_time_add[$i]="$DEFAULT_CONFIRM_TIME_ADD"
|
||
server_confirm_time_add_fail[$i]="$DEFAULT_CONFIRM_TIME_ADD_FAIL"
|
||
server_confirm_toggledownfall[$i]="$DEFAULT_CONFIRM_TOGGLEDOWNFALL"
|
||
server_confirm_toggledownfall_fail[$i]="$DEFAULT_CONFIRM_TOGGLEDOWNFALL_FAIL"
|
||
server_confirm_gamemode[$i]="$DEFAULT_CONFIRM_GAMEMODE"
|
||
server_confirm_gamemode_fail_no_user[$i]="$DEFAULT_CONFIRM_GAMEMODE_FAIL_NO_USER"
|
||
server_confirm_gamemode_fail_no_change[$i]="$DEFAULT_CONFIRM_GAMEMODE_FAIL_NO_CHANGE"
|
||
server_complete_backup_follow_symlinks[$i]="$DEFAULT_COMPLETE_BACKUP_FOLLOW_SYMLINKS"
|
||
|
||
|
||
# Load config overrides from server config file if present
|
||
|
||
if [[ -e "${server_conf[$i]}" ]]; then
|
||
local name
|
||
local value
|
||
|
||
while read line; do
|
||
# ignore comment lines
|
||
echo "$line" | grep "^#" >/dev/null 2>&1 && continue
|
||
|
||
# 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}')"
|
||
fi
|
||
|
||
case "$name" in
|
||
SERVER_USER) server_user_name[$i]="$value";;
|
||
SCREEN_NAME) server_screen_name[$i]="$value";;
|
||
WORLD_STORAGE_DIR) server_world_storage[$i]="${server_path[$i]}/$value";;
|
||
|
||
LOG) server_log[$i]="${server_path[$i]}/$value";;
|
||
PROPERTIES) server_properties[$i]="$value";;
|
||
WHITELIST) server_whitelist[$i]="$value";;
|
||
BANNED_PLAYERS) server_banned_players[$i]="$value";;
|
||
BANNED_IPS) server_banned_ips[$i]="$value";;
|
||
|
||
OPS) server_ops[$i]="$value";;
|
||
JAR) server_jar[$i]="${server_path[$i]}/$value";;
|
||
RAM) server_ram[$i]="$value";;
|
||
INVOCATION) server_invocation[$i]="$value";;
|
||
|
||
STOP_DELAY) server_stop_delay[$i]="$value";;
|
||
RESTART_DELAY) server_restart_delay[$i]="$value";;
|
||
STOP_MESSAGE) server_stop_message[$i]="$value";;
|
||
STOP_ABORT) server_stop_abort[$i]="$value";;
|
||
RESTART_MESSAGE) server_restart_message[$i]="$value";;
|
||
RESTART_ABORT) server_restart_abort[$i]="$value";;
|
||
WORLD_BACKUP_STARTED) server_world_backup_started[$i]="$value";;
|
||
WORLD_BACKUP_FINISHED) server_world_backup_finished[$i]="$value";;
|
||
|
||
COMPLETE_BACKUP_STARTED) server_complete_backup_started[$i]="$value";;
|
||
COMPLETE_BACKUP_FINISHED) server_complete_backup_finished[$i]="$value";;
|
||
CONFIRM_SAVE_ON) server_confirm_save_on[$i]="$value";;
|
||
CONFIRM_SAVE_OFF) server_confirm_save_off[$i]="$value";;
|
||
CONFIRM_SAVE_ALL) server_confrim_save_all[$i]="$value";;
|
||
CONFIRM_START) server_confrim_start[$i]="$value";;
|
||
CONFIRM_WHITELIST_LIST) server_confirm_whitelist_list[$i]="$value";;
|
||
CONFIRM_KICK) server_confirm_kick[$i]="$value";;
|
||
CONFIRM_KICK_FAIL) server_confirm_kick_fail[$i]="$value";;
|
||
CONFIRM_TIME_SET) server_confirm_time_set[$i]="$value";;
|
||
CONFIRM_TIME_SET_FAIL) server_confirm_time_set_fail[$i]="$value";;
|
||
CONFIRM_TIME_ADD) server_confirm_time_add[$i]="$value";;
|
||
CONFIRM_TIME_ADD_FAIL) server_confirm_time_add_fail[$i]="$value";;
|
||
CONFIRM_TOGGLEDOWNFALL) server_confirm_toggledownfall[$i]="$value";;
|
||
CONFIRM_TOGGLEDOWNFALL_FAIL) server_confirm_toggledownfall_fail[$i]="$value";;
|
||
CONFIRM_GAMEMODE) server_confirm_gamemode[$i]="$value";;
|
||
CONFIRM_GAMEMODE_FAIL_NO_USER) server_confirm_gamemode_fail_no_user[$i]="$value";;
|
||
CONFIRM_GAMEMODE_FAIL_NO_CHANGE) server_confirm_gamemode_fail_no_change[$i]="$value";;
|
||
COMPLETE_BACKUP_FOLLOW_SYMLINKS) server_complete_backup_follow_symlinks[$i]="$value";;
|
||
esac
|
||
done < "${server_conf[$i]}"
|
||
fi
|
||
|
||
# Replace tags in delay messages
|
||
server_stop_message[$i]="${server_stop_message[$i]//\{DELAY\}/${server_stop_delay[$i]}}"
|
||
server_restart_message[$i]="${server_restart_message[$i]//\{DELAY\}/${server_restart_delay[$i]}}"
|
||
|
||
# Replace tags in server invocation
|
||
server_invocation[$i]="${server_invocation[$i]//\{RAM\}/${server_ram[$i]}}"
|
||
server_invocation[$i]="${server_invocation[$i]//\{JAR\}/${server_jar[$i]}}"
|
||
|
||
|
||
# Load worlds if there is a world storage directory present
|
||
server_world_offset[$i]=0
|
||
server_num_worlds[$i]=0
|
||
|
||
if [[ -e "${server_world_storage[$i]}" ]]; then
|
||
server_worlds[$i]=$(ls -1 "${server_world_storage[$i]}")
|
||
|
||
# Record the index at which worlds for this server start
|
||
server_world_offset[$i]=$j
|
||
|
||
for world in ${server_worlds[$i]}; do
|
||
world_server_id[$j]="$i"
|
||
world_name[$j]="$world"
|
||
world_path[$j]="${server_world_storage[$i]}/${world_name[$j]}"
|
||
world_link[$j]="${server_path[$i]}/${world_name[$j]}"
|
||
world_flag_inram[$j]="${world_path[$j]}/$WORLD_FLAG_INRAM"
|
||
world_backup_path[$j]="$WORLD_ARCHIVE_PATH/${server_name[$i]}/${world_name[$j]}"
|
||
|
||
if [ ! -z $RAMDISK_STORAGE_PATH ]; then
|
||
world_ramdisk_path[$j]="${RAMDISK_STORAGE_PATH}/${server_name[$i]}/${world_name[$j]}"
|
||
fi
|
||
|
||
if [[ -e "${world_path[$j]}/$WORLD_FLAG_INRAM" ]]; then
|
||
world_inram[$j]="true"
|
||
else
|
||
world_inram[$j]="false"
|
||
fi
|
||
|
||
j=$(($j+1))
|
||
done
|
||
|
||
# Record the number of worlds this server has
|
||
server_num_worlds[$i]=$(( $j - ${server_world_offset[$i]} ))
|
||
fi
|
||
|
||
i=$(($i+1))
|
||
done
|
||
|
||
num_servers=$i
|
||
num_worlds=$j
|
||
}
|
||
|
||
# Called if the script is interrupted before exiting naturally
|
||
interrupt() {
|
||
local exit_message="false"
|
||
for ((i=0; $i<$num_servers; i++)); do
|
||
if [[ "${STOP_COUNTDOWN[$i]}" == "true" ]] && server_is_running $i; then
|
||
if [[ "$exit_message" == "false" ]]; then
|
||
echo -e "\nInterrupted..."
|
||
exit_message="true"
|
||
fi
|
||
server_eval $i "say ${server_stop_abort[$i]}"
|
||
echo "Server \"${server_name[$i]}\" shutdown was aborted."
|
||
fi
|
||
|
||
if [[ "${RESTART_COUNTDOWN[$i]}" == "true" ]] && server_is_running $i; then
|
||
if [[ "$exit_message" == "false" ]]; then
|
||
echo -e "\nInterrupted..."
|
||
exit_message="true"
|
||
fi
|
||
server_eval $i "say ${server_restart_abort[$i]}"
|
||
echo "Server \"${server_name[$i]}\" restart was aborted."
|
||
fi
|
||
done
|
||
exit
|
||
}
|
||
|
||
# The main function which starts the script
|
||
main() {
|
||
# Initialise variables that represent system state
|
||
init
|
||
|
||
# Trap interrupts to the script by calling the interrupt function
|
||
trap interrupt EXIT
|
||
|
||
case "$1" in
|
||
start)
|
||
# Required start option, for debian init.d scripts
|
||
for ((server=0; server<${num_servers}; server++)); do
|
||
# Only starts active servers
|
||
if ${server_active[$server]}; then
|
||
if server_is_running $server; then
|
||
echo "[ACTIVE] Server \"${server_name[$server]}\" already started."
|
||
else
|
||
echo "[ACTIVE] Server \"${server_name[$server]}\" starting:"
|
||
server_start $server
|
||
fi
|
||
else
|
||
if server_is_running $server; then
|
||
echo "[INACTIVE] Server \"${server_name[$server]}\" already started. It should not be running! Use \"$0 ${server_name[$server]} stop\" to stop this server."
|
||
else
|
||
echo "[INACTIVE] Server \"${server_name[$server]}\" leaving stopped, as this server is inactive."
|
||
fi
|
||
fi
|
||
done
|
||
;;
|
||
stop)
|
||
if [ "$2" != "now" ]; then
|
||
# If the the now flag is not specified
|
||
manager_stop_all_servers "stop"
|
||
else
|
||
# If the now flag is specified
|
||
manager_stop_all_servers_now
|
||
fi
|
||
;;
|
||
restart)
|
||
# Required restart option, for debian init.d scripts
|
||
|
||
# Stop any running servers, now if specified
|
||
echo "Stopping servers:"
|
||
main "stop" "$2"
|
||
|
||
echo "Starting servers:"
|
||
main "start"
|
||
;;
|
||
server)
|
||
case "$2" in
|
||
list)
|
||
# Lists the existing servers
|
||
server_list
|
||
;;
|
||
create)
|
||
if [ -z "$3" ]; then
|
||
# If a server name is not provided
|
||
echo "Invalid command."
|
||
else
|
||
# Create a new server
|
||
server_create "$3"
|
||
fi
|
||
;;
|
||
delete)
|
||
if [ -z "$3" ]; then
|
||
# If a server name is not provided
|
||
echo "Invalid command."
|
||
else
|
||
# Delete an existing server, with confirmation
|
||
server_delete "$3"
|
||
fi
|
||
;;
|
||
rename)
|
||
if [ -z "$3" ] || [ -z "$4" ]; then
|
||
# If a server name is not provided
|
||
echo "Invalid command."
|
||
else
|
||
# Rename an existing server
|
||
server_rename "$3" "$4"
|
||
fi
|
||
;;
|
||
*)
|
||
# "server" is not a valid command
|
||
echo "Invalid command."
|
||
;;
|
||
esac
|
||
;;
|
||
jargroup)
|
||
case "$2" in
|
||
list)
|
||
# Lists the jars grouped by jargroup
|
||
jargroup_list
|
||
;;
|
||
create)
|
||
if [ -z "$3" ] || [ -z "$4" ]; then
|
||
echo "Invlaid command."
|
||
else
|
||
jargroup_create "$3" "$4"
|
||
fi
|
||
;;
|
||
delete)
|
||
if [ -z "$3" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
jargroup_delete "$3"
|
||
fi
|
||
|
||
;;
|
||
rename)
|
||
if [ -z "$3" ] || [ -z "$4" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
jargroup_rename $3 $4
|
||
fi
|
||
;;
|
||
changetarget)
|
||
if [ -z "$3" ] || [ -z "$4" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
jargroup_settarget "$3" "$4"
|
||
fi
|
||
;;
|
||
getlatest)
|
||
if [ -z "$3" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
jargroup_getlatest "$3"
|
||
fi
|
||
;;
|
||
*)
|
||
# "jargroup" is not a valid command
|
||
echo "Invalid command."
|
||
;;
|
||
esac
|
||
;;
|
||
help)
|
||
# Outputs a list of all commands
|
||
echo -e "Usage: $0 command:"
|
||
echo -e
|
||
echo -e "--Setup Commands------------------------------------------------"
|
||
echo -e " server list \t\t\t\t\tList servers"
|
||
echo -e " server create <name> \t\t\t\tCreates a new Minecraft server"
|
||
echo -e " server delete <name> \t\t\t\tDeletes an existing Minecraft server"
|
||
echo -e " server rename <name> <new-name> \t\tRenames an existing Minecraft server"
|
||
echo -e
|
||
echo -e "--Server Mangement Commands-------------------------------------"
|
||
echo -e " <server> start \t\t\t\tStarts a server"
|
||
echo -e " <server> stop [now] \t\t\t\tStops a server after warning players, or right now"
|
||
echo -e " <server> restart [now] \t\t\tRestarts a server after warning players, or right now"
|
||
echo -e " <server> status \t\t\t\tShow the running/stopped status of a server"
|
||
echo -e " <server> connected \t\t\t\tList a servers connected players"
|
||
echo -e " <server> worlds list \t\t\t\tLists the worlds a server has"
|
||
echo -e " <server> worlds load \t\t\t\tCreates links to worlds in storage for a server"
|
||
echo -e " <server> worlds ram <world> \t\t\tToggles a world's \"in RAM\" status"
|
||
echo -e " <server> worlds toram \t\t\tSynchronises any RAM enabled worlds to RAM a server has"
|
||
echo -e " <server> worlds todisk \t\t\tSynchronises any \"in RAM\" worlds to disk a server has"
|
||
echo -e " <server> worlds backup \t\t\tMakes a backup of all worlds a server has"
|
||
echo -e " <server> logroll \t\t\t\tMove a server log to a gziped archive, to reduce lag"
|
||
echo -e " <server> backup \t\t\t\tMakes a backup of an entire server directory"
|
||
echo -e
|
||
echo -e "--Server Pass Through Commands----------------------------------"
|
||
echo -e " <server> wl on|off <player> \t\t\tEnabled/disable server whitelist check"
|
||
echo -e " <server> wl add|remove <player> \t\tAdd/remove a player to/from a server's whitelist"
|
||
echo -e " <server> wl list \t\t\t\tList the players whitelisted for a server"
|
||
echo -e " <server> bl player add|remove <player> \tBan/pardon a player from/for a server"
|
||
echo -e " <server> bl ip add|remove <ip address> \tBan/pardon an IP address from/for a server"
|
||
echo -e " <server> bl list \t\t\t\tLists the banned players and IP address for a server"
|
||
echo -e " <server> op add|remove <player> \t\tAdd/remove operator status for a player on a server"
|
||
echo -e " <server> gm survival|creative <player> \tChange the game mode for a player on a server"
|
||
echo -e " <server> kick <player> \t\t\tForcibly disconnect a player from a server"
|
||
echo -e " <server> say <message> \t\t\tBroadcast a (pink) message to all players on a server"
|
||
echo -e " <server> time set|add <number> \t\tSet/increment time on a server (0-24000)"
|
||
echo -e " <server> toggledownfall \t\t\tToggles rain and snow on a server"
|
||
echo -e " <server> save on|off \t\t\t\tEnable/disable writing world changes to file"
|
||
echo -e " <server> save all \t\t\t\tForce the writing of all non-saved world changes to file"
|
||
echo -e " <server> cmd <command> \t\t\tSend a command string to the server and return"
|
||
echo -e " <server> cmdlog <command> \t\t\tSame as 'cmd' but shows log output afterwards (Ctrl+C to exit)"
|
||
echo -e
|
||
echo -e "--Jar Commands--------------------------------------------------"
|
||
echo -e " jargroup list \t\t\t\tList the stored jar files."
|
||
echo -e " jargroup create <name> <download-url> \tCreate a new jar group, with a URL for new downloads"
|
||
echo -e " jargroup delete <name> \t\t\tDelete a jar group"
|
||
echo -e " jargroup rename <name> <new-name> \t\tRename a jar group"
|
||
echo -e " jargroup changeurl <name> <download-url> \tChange the download URL for a jar group"
|
||
echo -e " jargroup getlatest <name> \t\t\tDownload the latest jar file for a jar group"
|
||
echo -e
|
||
echo -e "--Global Commands-----------------------------------------------"
|
||
echo -e " start \t\t\t\t\tStarts all active servers"
|
||
echo -e " stop [now]\t\t\t\t\tStops all running servers"
|
||
echo -e " restart [now]\t\t\t\t\tRestarts all active servers"
|
||
;;
|
||
"")
|
||
echo "No such command see: $0 help"
|
||
;;
|
||
*)
|
||
if [[ "$1" == "all" ]] || [[ -e "$SERVER_STORAGE_PATH/$1" ]]; then
|
||
|
||
local id=$(server_get_id "$1")
|
||
|
||
case "$2" in
|
||
start)
|
||
server_set_active $id "active"
|
||
server_start $id
|
||
;;
|
||
stop)
|
||
server_set_active $id "inactive"
|
||
if [[ $3 != "now" ]]; then
|
||
server_stop $id
|
||
else
|
||
server_stop_now $id
|
||
fi
|
||
;;
|
||
restart)
|
||
server_set_active $1 "active"
|
||
if [[ $3 != "now" ]]; then
|
||
server_restart $id
|
||
else
|
||
server_restart_now $id
|
||
fi
|
||
;;
|
||
status)
|
||
if server_is_running $id; then
|
||
echo "Server \"${server_name[$id]}\" is running."
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is stopped."
|
||
fi
|
||
;;
|
||
connected)
|
||
server_connected $id
|
||
;;
|
||
worlds)
|
||
case "$3" in
|
||
list)
|
||
server_worlds_list $id
|
||
;;
|
||
load)
|
||
server_ensure_links $id
|
||
;;
|
||
ram)
|
||
if [ -z "$4" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
world_id=$(server_world_get_id $id "$4")
|
||
|
||
if [ ! -z $world_id ]; then
|
||
world_toggle_ramdisk_state $world_id
|
||
else
|
||
echo "Server \"${server_name[$id]}\" has no world with that name."
|
||
fi
|
||
fi
|
||
;;
|
||
todisk)
|
||
server_save_off $id
|
||
server_save_all $id
|
||
server_worlds_to_disk $id
|
||
server_save_on $id
|
||
;;
|
||
backup)
|
||
if server_is_running $id; then
|
||
server_eval $id "say ${server_world_backup_started[$id]}"
|
||
server_save_off $id
|
||
server_save_all $id
|
||
fi
|
||
|
||
server_worlds_to_disk $id
|
||
server_worlds_backup $id
|
||
|
||
if server_is_running $id; then
|
||
server_save_on $id
|
||
server_eval $id "say ${server_world_backup_finished[$id]}"
|
||
fi
|
||
|
||
echo "Backup took $SECONDS seconds".
|
||
;;
|
||
*)
|
||
echo "Invalid command."
|
||
;;
|
||
esac
|
||
;;
|
||
logroll)
|
||
server_log_roll $id
|
||
;;
|
||
backup)
|
||
if server_is_running $id; then
|
||
server_eval $id "say ${server_complete_backup_started[$id]}"
|
||
server_save_off $id
|
||
server_save_all $id
|
||
fi
|
||
|
||
server_worlds_to_disk $id
|
||
server_backup $id
|
||
|
||
if server_is_running $id; then
|
||
server_save_on $id
|
||
server_eval $id "say ${server_complete_backup_finished[$id]}"
|
||
fi
|
||
|
||
echo "Backup took $SECONDS seconds".
|
||
;;
|
||
jar)
|
||
if [ -z "$3" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
server_set_jar $id "$3"
|
||
fi
|
||
;;
|
||
whitelist|wl)
|
||
case "$3" in
|
||
on)
|
||
if server_is_running $id; then
|
||
server_eval $id "whitelist on"
|
||
echo "Whitelist enabled"
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
;;
|
||
off)
|
||
if server_is_running $id; then
|
||
server_eval $id "whitelist off"
|
||
echo "Whitelist disabled"
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
;;
|
||
add)
|
||
if [ -z "$4" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
if server_is_running $id; then
|
||
server_eval $id "whitelist add $4"
|
||
echo "Added \"$4\" to the whitelist."
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
fi
|
||
;;
|
||
remove)
|
||
if [ -z "$4" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
if server_is_running $id; then
|
||
server_eval $id "whitelist remove $4"
|
||
echo "Removed \"$4\" from the whitelist."
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
fi
|
||
;;
|
||
list)
|
||
local players=$(cat ${server_whitelist[$id]})
|
||
|
||
if [ -z "$players" ]; then
|
||
echo "No players are whitelisted."
|
||
else
|
||
echo "$players"
|
||
fi
|
||
;;
|
||
*)
|
||
echo "Invalid command."
|
||
;;
|
||
esac
|
||
;;
|
||
blacklist|bl)
|
||
case "$3" in
|
||
player)
|
||
if [ -z "$5" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
case "$4" in
|
||
add)
|
||
for player in ${*:5}; do
|
||
server_eval $id "ban $player"
|
||
done
|
||
if [[ $# > 5 ]]; then
|
||
echo -n "Blacklisted the following players: "
|
||
echo -n "$5"
|
||
for player in ${*:6}; do
|
||
echo -n ", $player"
|
||
done
|
||
echo "."
|
||
else
|
||
echo "Blacklisted \"$5\"."
|
||
fi
|
||
;;
|
||
remove)
|
||
for player in ${*:5}; do
|
||
server_eval $id "pardon $player"
|
||
done
|
||
if [[ $# > 5 ]]; then
|
||
echo -n "Removed the following players from the blacklist: "
|
||
echo -n "$5"
|
||
for player in ${*:6}; do
|
||
echo -n ", $player"
|
||
done
|
||
echo "."
|
||
else
|
||
echo "Removed \"$5\" from the blacklist."
|
||
fi
|
||
;;
|
||
*)
|
||
echo "Invalid command."
|
||
;;
|
||
esac
|
||
fi
|
||
;;
|
||
ip)
|
||
case "$4" in
|
||
add)
|
||
for address in ${*:5}; do
|
||
server_eval $id "ban-ip $address"
|
||
done
|
||
if [[ $# > 5 ]]; then
|
||
echo -n "Blacklisted the following ip addresses: "
|
||
echo -n "$5"
|
||
for player in ${*:6}; do
|
||
echo -n ", $address"
|
||
done
|
||
echo "."
|
||
else
|
||
echo "Blacklisted \"$5\"."
|
||
fi
|
||
;;
|
||
remove)
|
||
for address in ${*:5}; do
|
||
server_eval $id "pardon-ip $address"
|
||
done
|
||
if [[ $# > 5 ]]; then
|
||
echo -n "Removed the following ip addresses from the blacklist: "
|
||
echo -n "$5"
|
||
for player in ${*:6}; do
|
||
echo -n ", $address"
|
||
done
|
||
echo "."
|
||
else
|
||
echo "Removed \"$5\" from the ip blacklist."
|
||
fi
|
||
;;
|
||
*)
|
||
echo "Invalid command."
|
||
;;
|
||
esac
|
||
;;
|
||
list)
|
||
local players=$(cat ${server_banned_players[$id]})
|
||
|
||
local ips=$(cat ${server_banned_ips[$id]})
|
||
|
||
if [[ -z "$players" && -z "$ips" ]]; then
|
||
echo "The blacklist is empty."
|
||
else
|
||
if [[ ! -z "$players" ]]; then
|
||
echo "Players:"
|
||
for name in $players; do
|
||
echo " $name"
|
||
done
|
||
fi
|
||
|
||
if [[ ! -z "$ips" ]]; then
|
||
echo "IP Addresses:"
|
||
for address in $ips; do
|
||
echo " $address"
|
||
done
|
||
fi
|
||
fi
|
||
;;
|
||
*)
|
||
echo "Invalid command."
|
||
;;
|
||
esac
|
||
;;
|
||
operator|op)
|
||
case "$3" in
|
||
add)
|
||
if server_is_running $id; then
|
||
server_eval $id "op $4"
|
||
echo "The player \"$4\" is now an operator for the server."
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
;;
|
||
remove)
|
||
if server_is_running $id; then
|
||
server_eval $id "deop $4"
|
||
echo "The player \"$4\" is no longer an operator for the server."
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
;;
|
||
*)
|
||
echo "Invalid command"
|
||
;;
|
||
esac
|
||
;;
|
||
gamemode|gm)
|
||
case "$3" in
|
||
survival|creative|0|1)
|
||
if [ -z "$4" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
if server_is_running $id; then
|
||
case "$3" in
|
||
creative|1) local mode=1;;
|
||
survival|0) local mode=0;;
|
||
*) echoerr "Invalid mode"; exit 1;;
|
||
esac
|
||
|
||
local line=$(server_eval_and_get_line $id "gamemode $4 $mode" "${server_confirm_gamemode[$id]}" "${server_confirm_gamemode_fail_no_user[$id]}" "${server_confirm_gamemode_fail_no_change[$id]}")
|
||
|
||
local regex="${LOG_REGEX} ${server_confirm_gamemode[$id]}"
|
||
if [[ $line =~ $regex ]]; then
|
||
echo "Changed game mode of \"$4\" to \"$3\"."
|
||
fi
|
||
local regex="${LOG_REGEX} ${server_confirm_gamemode_fail_no_user[$id]}"
|
||
if [[ $line =~ $regex ]]; then
|
||
echo "The player \"$4\" was not found to be logged on."
|
||
fi
|
||
local regex="${LOG_REGEX} ${server_confirm_gamemode_fail_no_change[$id]}"
|
||
if [[ $line =~ $regex ]]; then
|
||
echo "The player \"$4\" was already in \"$3\" mode."
|
||
fi
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
fi
|
||
;;
|
||
*)
|
||
echo "Invalid command."
|
||
;;
|
||
esac
|
||
;;
|
||
kick)
|
||
if [ -z "$3" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
if server_is_running $id; then
|
||
local line=$(server_eval_and_get_line $id "kick $3" "${server_confirm_kick[$id]}" "${server_confirm_kick_fail[$id]}")
|
||
|
||
local regex="${LOG_REGEX} ${server_confirm_kick[$id]}"
|
||
if [[ $line =~ $regex ]]; then
|
||
echo "Kicked \"$3\" from game."
|
||
fi
|
||
local regex="${LOG_REGEX} ${server_confirm_kick_fail[$id]}"
|
||
if [[ $line =~ $regex ]]; then
|
||
echo "The player \"$3\" is not connected."
|
||
fi
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
fi
|
||
;;
|
||
say)
|
||
if [ -z "$3" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
if server_is_running $id; then
|
||
server_eval $id "say ${*:3}"
|
||
echo "Message sent to players."
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
fi
|
||
;;
|
||
time)
|
||
case "$3" in
|
||
set)
|
||
if [ -z "$4" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
if server_is_running $id; then
|
||
local line=$(server_eval_and_get_line $id "time set $4" "${server_confirm_time_set[$id]}" "${server_confirm_time_set_fail[$id]}")
|
||
|
||
local regex="${LOG_REGEX} ${server_confirm_time_set[$id]}"
|
||
if [[ $line =~ $regex ]]; then
|
||
echo "Set time to \"$4\"."
|
||
fi
|
||
local regex="${LOG_REGEX} ${server_confirm_time_set_fail[$id]}"
|
||
if [[ $line =~ $regex ]]; then
|
||
echo "Unable to convert \"$4\" to a time."
|
||
fi
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
fi
|
||
;;
|
||
add)
|
||
if [ -z "$4" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
if server_is_running $id; then
|
||
local line=$(server_eval_and_get_line $id "time add $4" "${server_confirm_time_add[$id]}" "${server_confirm_time_add_fail[$id]}")
|
||
|
||
local regex="${LOG_REGEX} ${server_confirm_time_add[$id]}"
|
||
if [[ $line =~ $regex ]]; then
|
||
echo "Added \"$4\" to time."
|
||
fi
|
||
local regex="${LOG_REGEX} ${server_confirm_time_add_fail[$id]}"
|
||
if [[ $line =~ $regex ]]; then
|
||
echo "Unable to convert \"$4\" to a time."
|
||
fi
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
fi
|
||
;;
|
||
*)
|
||
echo "Invalid command."
|
||
;;
|
||
esac
|
||
;;
|
||
toggledownfall|tdf)
|
||
if server_is_running $id; then
|
||
local line=$(server_eval_and_get_line $id "toggledownfall $3" "${server_confirm_toggledownfall[$id]}" "${server_confirm_toggledownfall_fail[$id]}")
|
||
|
||
local regex="${LOG_REGEX} ${server_confirm_toggledownfall[$id]}"
|
||
if [[ $line =~ $regex ]]; then
|
||
echo ${line:36:(-3)}
|
||
fi
|
||
local regex="${LOG_REGEX} ${server_confirm_toggledownfall_fail[$id]}"
|
||
if [[ $line =~ $regex ]]; then
|
||
echo ${line:34:(-3)}
|
||
fi
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
;;
|
||
save)
|
||
case "$3" in
|
||
on)
|
||
server_save_on $id
|
||
;;
|
||
off)
|
||
server_save_off $id
|
||
;;
|
||
all)
|
||
server_save_all $id
|
||
;;
|
||
*)
|
||
echo "Invalid command."
|
||
;;
|
||
esac
|
||
;;
|
||
cmd)
|
||
if [ -z "$3" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
if server_is_running $id; then
|
||
server_eval $id "${*:3}"
|
||
echo "Command sent."
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
fi
|
||
;;
|
||
cmdlog)
|
||
if [ -z "$3" ]; then
|
||
echo "Invalid command."
|
||
else
|
||
if server_is_running $id; then
|
||
server_eval $id "${*:3}"
|
||
echo "Now watching logs (press Ctrl+C to exit):"
|
||
as_user ${server_user_name[$id]} "tail --follow --lines=0 --sleep-interval=0.1 ${server_log[$id]}"
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
fi
|
||
;;
|
||
console)
|
||
if server_is_running $id; then
|
||
as_user ${server_user_name[$1]} "screen -r ${server_screen_name[$1]}"
|
||
else
|
||
echo "Server \"${server_name[$id]}\" is not running."
|
||
fi
|
||
;;
|
||
*)
|
||
echo "Invalid command."
|
||
;;
|
||
esac
|
||
else
|
||
echo "No server with that name."
|
||
fi
|
||
;;
|
||
esac
|
||
}
|
||
|
||
|
||
### Start point
|
||
|
||
main "$@"
|
||
exit 0
|