Skip to content

Instantly share code, notes, and snippets.

@bortels
Created October 2, 2012 17:02
Show Gist options
  • Save bortels/3821177 to your computer and use it in GitHub Desktop.
Save bortels/3821177 to your computer and use it in GitHub Desktop.
minecraft control script using screen
#! /bin/sh
### BEGIN INIT INFO
# Provides: minecraft_server
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Minecraft Server control script.
# Description: Minecraft Server control script.
# Options
# start <world> - Start the Minecraft world server. Starts all world servers by default.
# stop <world> - Stop the Minecraft world server. Stops all world servers by default.
# force-stop <world> - Forcibly stop the Minecraft world server. Forcibly stops all world servers by default.
# restart <world> - Restart the Minecraft world server. Restarts all world servers by default.
# force-restart <world> - Forcibly restart the Minecraft world server. Forcibly restarts all world servers by default.
# status <world> - Display the status of the Minecraft world server. Displays the status of all world servers by default.
# send <world> <command> - Send a command to a Minecraft world server.
# screen <world> - Display the Screen for the Minecraft world server.
# watch <world> - Watch the log file for the Minecraft world server.
# backup <world> - Backup the Minecraft world. Backup all worlds by default.
# c10t <world> - Run the c10t mapping software on the Minecraft world. Maps all worlds by default.
# update <software> - Update a software package. Update the server software and all addons by default.
# Available software options
# mcserver - Minecraft server software.
# bukkit - Craft Bukkit server software.
# c10t - c10t mapping software.
### END INIT INFO
USER_NAME=minecraft
# The location of server software and data.
LOCATION="/home/$USER_NAME"
## Required software.
JAVA=$(which java)
PERL=$(which perl)
SCREEN=$(which screen)
WGET=$(which wget)
## Minecraft software options.
# Generic server options.
INITIAL_MEMORY="1024M"
MAXIMUM_MEMORY="2048M"
# Automatically restart the Minecraft server when a SEVERE error is caught.
# 0 - Do not auto restart.
# 1 - Auto restart.
AUTO_RESTART_ON_ERROR=1
# Server software to use.
# mcserver - Minecraft server software.
# bukkit - Craft Bukkit server software.
#SERVER_TYPE="mcserver"
SERVER_TYPE="bukkit"
# Software packages, used for updating.
# mcserver - Minecraft server software.
# bukkit - Craft Bukkit server software.
# c10t - c10t mapping software.
# Available software packages.
AVAILABLE_PACKAGES="mcserver bukkit c10t"
# Software packages updated with update command.
UPDATE_PACKAGES="$SERVER_TYPE c10t"
# User Commands that are available to your Minecraft players.
# motd - Whispers the MOTD to the player, in case they missed it when they logged in.
# help - Whispers the content of the help file. A default help file will be generated on the first run.
USER_COMMANDS="motd help"
# Minecraft server options.
MCSERVER_URL="http://www.minecraft.net/download/minecraft_server.jar"
MCSERVER_LOCATION="$LOCATION/minecraft_server"
MCSERVER_JAR="$MCSERVER_LOCATION/minecraft_server.jar"
MCSERVER_ARGS="nogui"
MCSERVER_COMMAND="$JAVA -Xms$INITIAL_MEMORY -Xmx$MAXIMUM_MEMORY -jar $MCSERVER_JAR $MCSERVER_ARGS"
# Bukkit server options.
#BUKKIT_URL="http://ci.bukkit.org/job/dev-CraftBukkit/promotion/latest/Recommended/artifact/target/craftbukkit-1.0.1-SNAPSHOT.jar"
#BUKKIT_URL="http://ci.bukkit.org/job/dev-CraftBukkit/promotion/latest/Recommended/artifact/target/craftbukkit-1.0.1-R1.jar"
# DEV
# BUKKIT_URL="http://ci.bukkit.org/job/dev-CraftBukkit/lastSuccessfulBuild/artifact/target/craftbukkit-1.1-R1-SNAPSHOT.jar"
#BUKKIT_URL="http://ci.bukkit.org/job/dev-CraftBukkit/1818/artifact/target/craftbukkit-1.1-R1.jar"
# BUKKIT_URL="http://ci.bukkit.org/job/dev-CraftBukkit/lastSuccessfulBuild/artifact/target/craftbukkit-1.1-R5-SNAPSHOT.jar"
BUKKIT_URL="http://cbukk.it/craftbukkit.jar"
BUKKIT_LOCATION="$LOCATION/minecraft_server"
# BUKKIT_JAR="$BUKKIT_LOCATION/craftbukkit.jar"
BUKKIT_JAR="$BUKKIT_LOCATION/craftbukkit-dev.jar"
BUKKIT_ARGS="nogui"
BUKKIT_COMMAND="$JAVA -Xms$INITIAL_MEMORY -Xmx$MAXIMUM_MEMORY -jar $BUKKIT_JAR $BUKKIT_ARGS"
echo $BUKKIT_COMMAND
# c10t mapping software options.
C10T_URL="http://toolchain.eu/minecraft/c10t/releases"
C10T_LOCATION="$LOCATION/c10t"
C10T_BIN="$C10T_LOCATION/c10t"
# Location to place map images, and the URL displayed to users for map access.
MAPS_URL="http://home.bortels.us/maps"
MAPS_LOCATION="$LOCATION/maps"
## Lib-notify configuration
# To use lib-notify to print a message on your desktop of important server events, change the following to a 1.
USE_LIBNOTIFY=1
# The username and display that notifications will be routed to.
LIBNOTIFY_USER_NAME=bortels
LIBNOTIFY_DISPLAY=":0.0"
## World configuration.
WORLDS_LOCATION="$LOCATION/worlds"
# List of worlds and the ports they are running on. This file will
# be generated if missing.
# Note: World name should not contain a space, at least for now.
# ie:
# alpha 25565
# beta 25566
WORLDS_CONF="$LOCATION/worlds.conf"
# Default world name and port if worlds.conf is missing.
DEFAULT_WORLD="world"
DEFAULT_PORT="25565"
## Message of the day file, displayed to users on login.
MOTD="$LOCATION/motd.txt"
## Help file.
HELP="$LOCATION/help.txt"
## Backup configuration.
BACKUP_LOCATION="$LOCATION/backups"
# Length in days that backups survive.
BACKUP_FULL_DURATION=14
## Internal Methods.
execute() {
# Execute the given command.
# ARGS: command user
if [ $(id -u) = 0 ]; then
# Script is running as root, switch user and execute the command.
su -c "$1" $2
else
# Script is running as a user, just execute the command.
sh -c "$1"
fi
}
getProcessIDs() {
# Get the PIDs of the Screen and Java process for the world server.
# ARGS: world
local SCREEN_PID JAVA_PID
SCREEN_PID=$(execute "$SCREEN -ls" $USER_NAME | $PERL -ne 'if ($_ =~ /^\t(\d+)\.minecraft-'$1'/) { print $1; }')
JAVA_PID=$(ps -a -u $USER_NAME -o pid,ppid,comm | $PERL -ne 'if ($_ =~ /^\s*(\d+)\s+'$SCREEN_PID'\s+java/) { print $1; }')
echo "$SCREEN_PID $JAVA_PID"
}
serverRunning() {
# Check to see if the world server is running.
# ARGS: world
local PIDS
PIDS=$(getProcessIDs $1)
# Try to determine if the world is running.
if [ -n "$(echo $PIDS | cut -d ' ' -f1)" ] && [ -n "$(echo $PIDS | cut -d ' ' -f2)" ]; then
echo 1
else
echo 0
fi
}
sendCommand() {
# Send a command to the world server.
# ARGS: world command
local COMMAND
COMMAND=$(printf "$2\r")
execute "$SCREEN -S minecraft-$1 -p 0 -X stuff \"$COMMAND\"" $USER_NAME
if [ ! $? = 0 ]; then
printf "Error sending command to server $1.\n"
exit 1
fi
}
displayScreen() {
# Connect to the Screen of a world server.
# ARGS: world
execute "$SCREEN -x minecraft-$1" $USER_NAME
if [ ! $? = 0 ]; then
printf "Error connecting to Screen.\n"
exit 1
fi
}
listContains() {
# Check whether the item is in the list.
# ARGS: item list
local MATCH ITEM
MATCH=0
for ITEM in $2; do
if [ "$ITEM" = "$1" ]; then
MATCH=1
fi
done
echo $MATCH
}
getPort() {
# Grab the port for the given world.
# ARGS: world
local PORT
PORT=$(execute "cat $WORLDS_CONF" $USER_NAME | $PERL -ne 'if ($_ =~ /^'$1'\s+(\d+)/) { print "$1"; }')
echo $PORT
}
getWorlds() {
# Grab the list of worlds.
local WORLDS
WORLDS=$(execute "cat $WORLDS_CONF" $USER_NAME | $PERL -ne 'if ($_ =~ /^(\w+)\s+\d+/) { print "$1 "; }')
echo $WORLDS
}
libNotify() {
# Send a message to the desktop using lib-notify, if it is available.
# ARGS: summary body
local NOTIFY
NOTIFY=$(which notify-send)
if [ -e $NOTIFY ]; then
execute "DISPLAY=$LIBNOTIFY_DISPLAY $NOTIFY \"$1\" \"$2\"" $LIBNOTIFY_USER_NAME > /dev/null 2>&1
fi
}
tellMOTD() {
# Send the Message Of The Day (MOTD) to the user.
# ARGS: world user
local LINE
if [ -e $MOTD ]; then
while read LINE; do
sendCommand $1 "tell $2 $LINE"
done < $MOTD
fi
}
tellHelp() {
# Send help to the user.
# ARGS: world user
local LINE
# If the help file does not exist, create a default one.
if [ ! -e $HELP ]; then
execute "printf \"§fAvailable commands: $USER_COMMANDS\n\" > $HELP" $USER_NAME
fi
while read LINE; do
sendCommand $1 "tell $2 $LINE"
done < $HELP
}
checkForLogin() {
# Check for users logging into a world.
# ARGS: world message
local LOGIN PLAYER_NAME
LOGIN=$(echo "$2" | $PERL -ne 'if ($_ =~ /(\w+) \[\/([0-9\.]+)\:(\d+)\] logged in with entity id (\d+)/) { print "$1\t$2\t$3\t$4"; }')
if [ -n "$LOGIN" ]; then
PLAYER_NAME=$(printf "$LOGIN" | cut -f1)
# Add the user to the world.users file.
execute "printf \"$LOGIN\n\" >> \"$WORLDS_LOCATION/$1.users\"" $USER_NAME
# Announce the user logging in via lib-notify.
if [ $USE_LIBNOTIFY ]; then
libNotify "Minecraft - $1" "$PLAYER_NAME has logged into world."
fi
# Whisper the MOTD to the user logging in.
tellMOTD $1 $PLAYER_NAME
fi
}
checkForLogout() {
# Check for users logging out of a world.
# ARGS: world message
local LOGOUT PLAYER_NAME
LOGOUT=$(echo "$2" | $PERL -ne 'if ($_ =~ /(\w+) lost connection\: (.+)/) { print "$1\t$2"; }')
if [ -n "$LOGOUT" ]; then
PLAYER_NAME=$(printf "$LOGOUT" | cut -f1)
# Remove the user from the world.users file.
execute "perl -i -ne 'print unless /^$PLAYER_NAME\t[0-9\.]+\t\d+\d+/;' $WORLDS_LOCATION/$1.users" $USER_NAME
# Announce the user logging out via lib-notify.
if [ $USE_LIBNOTIFY ]; then
libNotify "Minecraft - $1" "$PLAYER_NAME has logged out of world."
fi
fi
}
checkForCommand() {
# Check for users attempting to execute a command.
# ARGS: world message
local COMMAND PLAYER_NAME
COMMAND=$(echo "$2" | $PERL -ne 'if ($_ =~ /(\w+) tried command\: (.+)/) { print "$1\t$2"; }')
if [ -n "$COMMAND" ]; then
PLAYER_NAME=$(printf "$COMMAND" | cut -f1)
COMMAND=$(printf "$COMMAND" | cut -f2)
if [ $(listContains $COMMAND "$USER_COMMANDS") = 1 ]; then
case "$COMMAND" in
motd)
tellMOTD $1 $PLAYER_NAME
;;
help)
tellHelp $1 $PLAYER_NAME
;;
*)
;;
esac
fi
fi
}
parseLog() {
# Parse through the log file for the given world.
# ARGS: world
local LINE DATE TIME TYPE MESSAGE
while read LINE; do
LINE=$(echo "$LINE" | $PERL -ne 'if ($_ =~ /(.+) (.+) \[(\w+)\] (.+)/) { print "$1\t$2\t$3\t$4"; }')
DATE=$(echo "$LINE" | cut -f1)
TIME=$(echo "$LINE" | cut -f2)
TYPE=$(echo "$LINE" | cut -f3)
MESSAGE=$(echo "$LINE" | cut -f4)
case "$TYPE" in
INFO)
checkForLogin $1 "$MESSAGE"
checkForLogout $1 "$MESSAGE"
checkForCommand $1 "$MESSAGE"
;;
SEVERE)
if [ $AUTO_RESTART_ON_ERROR = 1 ]; then
sendCommand $1 "say The server is experiencing issues, restarting in 5 seconds..."
sleep 5
forceStop $1
sleep 5
start $1
fi
;;
WARNING)
;;
*)
;;
esac
done
}
watchLog() {
# Watch the world server log file.
# ARGS: world
local PID
# Make sure that the server.log file exists.
if [ -e "$WORLDS_LOCATION/$1/server.log" ]; then
# Watch the log.
PID=$(echo $(getProcessIDs $1) | cut -d ' ' -f2)
tail -n0 -f --pid=$PID $WORLDS_LOCATION/$1/server.log
fi
}
start() {
# Start the world server.
# ARGS: world
local SERVER_PORT PID
# Make sure that the server directory exists.
execute "mkdir -p $WORLDS_LOCATION/$1" $USER_NAME
cd $WORLDS_LOCATION/$1
# Make sure that the server.properties file exists.
if [ ! -e server.properties ]; then
SERVER_PORT=$(getPort $1)
execute "printf \"# Minecraft server properties\n\" > server.properties" $USER_NAME
execute "printf \"level-name=$1\n\" >> server.properties" $USER_NAME
execute "printf \"server-port=$SERVER_PORT\n\" >> server.properties" $USER_NAME
fi
# Make sure that the server.log file exists.
execute "touch server.log" $USER_NAME
# Erase the world's users file before starting up the world (should already be empty).
execute "printf \"\" > \"$WORLDS_LOCATION/$1.users\"" $USER_NAME
# Start the server.
execute "$SCREEN -dmS minecraft-$1 $SERVER_COMMAND" $USER_NAME
if [ ! $? = 0 ]; then
printf "Error starting the server.\n"
exit 1
fi
# Start the log processor.
PID=$(echo $(getProcessIDs $1) | cut -d ' ' -f2)
tail -n0 -f --pid=$PID $WORLDS_LOCATION/$1/server.log | parseLog $1 &
}
stop() {
# Stop the world server.
# ARGS: world
sendCommand $1 "stop"
# Erase the world's users file since we won't be able to catch anyone logging off.
execute "printf \"\" > \"$WORLDS_LOCATION/$1.users\"" $USER_NAME
}
forceStop() {
# Forcibly stop the world server.
# ARGS: world
local PIDS
PIDS=$(getProcessIDs $1)
# Try to stop the server cleanly first.
stop $1
sleep 5
# Kill the process ids of the world server.
kill -9 $PIDS > /dev/null 2>&1
}
fullBackup() {
# Backup the world server.
# ARGS: world
local DATE NUM
# Make sure that the backup location exists.
execute "mkdir -p $BACKUP_LOCATION" $USER_NAME
cd $WORLDS_LOCATION
# Grab the date.
DATE=$(date +%Y-%m-%d)
# Make sure that we are using a unique filename for this backup.
NUM=0
while [ -e $BACKUP_LOCATION/fullBackup-$1-$DATE-$NUM.tar.gz ]; do
NUM=$(($NUM + 1))
done
# Create the full backup file.
execute "tar -chzf $BACKUP_LOCATION/fullBackup-$1-$DATE-$NUM.tar.gz $1" $USER_NAME
# Cleanup old backups.
execute "find $BACKUP_LOCATION -name fullBackup-$1-* -type f -mtime +$BACKUP_FULL_DURATION -delete" $USER_NAME
}
updateServerSoftware() {
# Update server software.
# Args: file location url
execute "mkdir -p $2" $USER_NAME
# Backup the old server jar.
if [ -e $1 ]; then
execute "mv -f $1 $1.old" $USER_NAME
fi
# Download the new server software.
execute "$WGET -qO $1 $3" $USER_NAME
# Check for error and restore backup if found.
if [ ! $? = 0 ]; then
printf "\nError updating server software.\n"
if [ -e "$1.old" ]; then
execute "mv -f $1.old $1" $USER_NAME
fi
exit 1
fi
}
updateMappingSoftware() {
# Update the c10t mapping software.
local ARCH VERSION
# Make sure the directory exists.
execute "mkdir -p $C10T_LOCATION" $USER_NAME
cd $C10T_LOCATION
# Determine the architecture of the system.
if [ $(getconf LONG_BIT) = 64 ]; then
ARCH="x86_64"
else
ARCH="x86"
fi
# Determine the current version number of c10t.
execute "$WGET -qO CURRENT $C10T_URL/CURRENT" $USER_NAME
if [ ! $? = 0 ]; then
printf "\nError determining the current version of c10t.\n"
exit 1
fi
VERSION=$(execute "cat CURRENT")
# Download the new version of c10t.
execute "$WGET -qO c10t.tar.gz $C10T_URL/c10t-$VERSION-linux-$ARCH.tar.gz" $USER_NAME
if [ ! $? = 0 ]; then
printf "\nError updating c10t.\n"
exit 1
fi
# Uncompress the archive.
execute "tar xzf c10t.tar.gz --strip 1" $USER_NAME
}
update() {
# Update software package.
# ARGS: package
case "$1" in
mcserver)
updateServerSoftware "$MCSERVER_JAR" "$MCSERVER_LOCATION" "$MCSERVER_URL"
;;
bukkit)
updateServerSoftware "$BUKKIT_JAR" "$BUKKIT_LOCATION" "$BUKKIT_URL"
;;
c10t)
updateMappingSoftware
;;
*)
printf "Unknown software package: $1\n"
exit 1
;;
esac
}
c10t() {
# Run c10t mapping software on the server.
# ARGS: world
execute "mkdir -p $MAPS_LOCATION/$1" $USER_NAME
# Make sure that the world files are actually there before mapping.
if [ -e "$WORLDS_LOCATION/$1/server.properties" ]; then
# Create various maps for the main world.
execute "$C10T_BIN -s -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/surface.png" $USER_NAME > /dev/null 2>&1
execute "$C10T_BIN -s -c -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/caves.png" $USER_NAME > /dev/null 2>&1
execute "$C10T_BIN -s -c -H -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/caves_heightmap.png" $USER_NAME > /dev/null 2>&1
execute "$C10T_BIN -s -a -i 21 -H -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/lapis_heightmap.png" $USER_NAME > /dev/null 2>&1
execute "$C10T_BIN -s -a -i 56 -H -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/diamonds_heightmap.png" $USER_NAME > /dev/null 2>&1
execute "$C10T_BIN -s -a -i 4 -H -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/cobble_heightmap.png" $USER_NAME > /dev/null 2>&1
execute "$C10T_BIN -s -q -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/surface_oblique.png" $USER_NAME > /dev/null 2>&1
execute "$C10T_BIN -s -q -c -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/caves_oblique.png" $USER_NAME > /dev/null 2>&1
execute "$C10T_BIN -s -z -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/surface_isometric.png" $USER_NAME > /dev/null 2>&1
execute "$C10T_BIN -s -z -c -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/caves_isometric.png" $USER_NAME > /dev/null 2>&1
# Create various maps for the nether world if it exists.
if [ -d "$WORLDS_LOCATION/$1/$1/DIM-1" ]; then
execute "$C10T_BIN -s -N --hell-mode -w $WORLDS_LOCATION/$1/$1/DIM-1 -o $MAPS_LOCATION/$1/nether_surface.png" $USER_NAME > /dev/null 2>&1
execute "$C10T_BIN -s -N --hell-mode -q -w $WORLDS_LOCATION/$1/$1/DIM-1 -o $MAPS_LOCATION/$1/nether_surface_oblique.png" $USER_NAME > /dev/null 2>&1
execute "$C10T_BIN -s -N --hell-mode -z -w $WORLDS_LOCATION/$1/$1/DIM-1 -o $MAPS_LOCATION/$1/nether_surface_isometric.png" $USER_NAME > /dev/null 2>&1
fi
fi
}
## Begin.
# Make sure that Java, Perl, GNU Screen, and GNU Wget are installed.
if [ ! -e $JAVA ]; then
printf "ERROR: Java not found!\n"
printf "Try installing this with:\n"
printf "sudo apt-get install openjdk-6-jre\n"
exit 1
fi
if [ ! -e $PERL ]; then
printf "ERROR: Perl not found!\n"
printf "Try installing this with:\n"
printf "sudo apt-get install perl\n"
exit 1
fi
if [ ! -e $SCREEN ]; then
printf "ERROR: GNU Screen not found!\n"
printf "Try installing this with:\n"
printf "sudo apt-get install screen\n"
exit 1
fi
if [ ! -e $WGET ]; then
printf "ERROR: GNU Wget not found!\n"
printf "Try installing this with:\n"
printf "sudo apt-get install wget\n"
exit 1
fi
# Make sure that the minecraft user exists.
if [ ! -n "$(grep $USER_NAME /etc/passwd)" ]; then
printf "ERROR: This script requires that a user account named $USER_NAME exist on this system.\n"
printf "Either modify the USER_NAME variable in this script, or try adding this user:\n"
printf "sudo adduser $USER_NAME\n"
exit 1
fi
# Warn if the script is running with the wrong user.
if [ ! $(id -u) = 0 ] && [ ! $(whoami) = $USER_NAME ]; then
printf "WARNING: This script appears to have been started by the wrong user.\n"
fi
# Make sure that the worlds.conf file exists.
if [ ! -e $WORLDS_CONF ]; then
execute "printf \"# Minecraft world configuration file\n\" > $WORLDS_CONF" $USER_NAME
execute "printf \"# <world>\t<port>\n\" >> $WORLDS_CONF" $USER_NAME
execute "printf \"$DEFAULT_WORLD\t$DEFAULT_PORT\n\" >> $WORLDS_CONF" $USER_NAME
fi
# Initialize some variables determined by the server type.
case "$SERVER_TYPE" in
mcserver)
SERVER_COMMAND=$MCSERVER_COMMAND
SERVER_FILE=$MCSERVER_JAR
;;
bukkit)
SERVER_COMMAND=$BUKKIT_COMMAND
SERVER_FILE=$BUKKIT_JAR
;;
*)
printf "Unknown server type: $SERVER_TYPE\n"
exit 1
;;
esac
# Grab the list of worlds.
WORLDS=$(getWorlds)
# Respond to the command line arguments.
case "$1" in
start)
# Make sure that the server software exists.
if [ ! -e $SERVER_FILE ]; then
printf "Server software not found, downloading it...\n"
update $SERVER_TYPE
fi
# Check for the optional world command line argument.
if [ -n "$2" ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
WORLDS="$2"
elif [ -n "$2" ]; then
printf "Minecraft world $2 not found!\n"
printf " Usage: $0 $1 <world>\n"
exit 1
fi
# Start each world requested, if not already running.
printf "Starting Minecraft Server:"
for WORLD in $WORLDS; do
if [ $(serverRunning $WORLD) = 0 ]; then
printf " $WORLD"
start $WORLD
fi
done
printf "\n"
;;
stop|force-stop)
# Check for the optional world command line argument.
if [ -n "$2" ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
WORLDS="$2"
elif [ -n "$2" ]; then
printf "Minecraft world $2 not found!\n"
printf " Usage: $0 $1 <world>\n"
exit 1
fi
# Stop each world requested, if running.
printf "Stopping Minecraft Server:"
for WORLD in $WORLDS; do
# Try to stop the world cleanly.
if [ $(serverRunning $WORLD) = 1 ]; then
printf " $WORLD"
sendCommand $WORLD "say The server is about to go down."
sendCommand $WORLD "save-all"
sendCommand $WORLD "save-off"
sendCommand $WORLD "say The server is going down in 5 seconds..."
sleep 5
if [ "$1" = "force-stop" ]; then
forceStop $WORLD
else
stop $WORLD
fi
sleep 5
fi
done
printf "\n"
;;
restart|reload|force-restart|force-reload)
# Check for the optional world command line argument.
if [ -n "$2" ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
WORLDS="$2"
elif [ -n "$2" ]; then
printf "Minecraft world $2 not found!\n"
printf " Usage: $0 $1 <world>\n"
exit 1
fi
# Restart each world requested, start those not already running.
printf "Restarting Minecraft Server:"
for WORLD in $WORLDS; do
printf " $WORLD"
if [ $(serverRunning $WORLD) = 1 ]; then
sendCommand $WORLD "say The server is about to restart."
sendCommand $WORLD "save-all"
sendCommand $WORLD "save-off"
sendCommand $WORLD "say Restarting in 5 seconds..."
sleep 5
if [ "$(echo \"$1\" | cut -d '-' -f1)" = "force" ]; then
forceStop $WORLD
else
stop $WORLD
fi
sleep 5
fi;
start $WORLD
done
printf "\n"
;;
status|show)
# Check for the optional world command line argument.
if [ -n "$2" ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
WORLDS="$2"
elif [ -n "$2" ]; then
printf "Minecraft world $2 not found!\n"
printf " Usage: $0 $1 <world>\n"
exit 1
fi
# Show the status of each world requested.
printf "Minecraft Server Status:\n"
for WORLD in $WORLDS; do
printf " $WORLD: "
if [ $(serverRunning $WORLD) = 1 ]; then
printf "running (%d users online)\n" $(cat $WORLDS_LOCATION/$WORLD.users | wc -l)
else
printf "not running.\n"
fi
done
;;
send)
# Check for the world command line argument.
if [ -n "$2" ] && [ $(listContains $2 "$WORLDS") = 1 ] && [ -n "$3" ]; then
WORLD=$2
shift 2
printf "Send command to world $WORLD: $*\n"
sendCommand $WORLD "$*"
else
printf "Usage: $0 $1 <world> <command>\n"
printf " ie: $0 $1 world say Hello World!\n"
exit 1
fi
;;
screen)
# Check for the world command line argument.
if [ -n "$2" ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
displayScreen $2
else
if [ -n "$2" ]; then
printf "Minecraft world $2 not found!\n"
else
printf "Minecraft world not provided!\n"
fi
printf " Usage: $0 $1 <world>\n"
exit 1
fi
;;
watch)
# Check for the world command line argument.
if [ -n "$2" ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
watchLog $2
else
if [ -n "$2" ]; then
printf "Minecraft world $2 not found!\n"
else
printf "Minecraft world not provided!\n"
fi
printf " Usage: $0 $1 <world>\n"
exit 1
fi
;;
backup)
# Check for the optional world command line argument.
if [ -n "$2" ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
WORLDS="$2"
elif [ -n "$2" ]; then
printf "Minecraft world $2 not found!\n"
printf " Usage: $0 $1 <world>\n"
exit 1
fi
# Backup each world requested.
printf "Backing up Minecraft Server:"
for WORLD in $WORLDS; do
printf " $WORLD"
if [ $(serverRunning $WORLD) = 1 ]; then
sendCommand $WORLD "say Backing up the world."
sendCommand $WORLD "save-all"
sendCommand $WORLD "save-off"
sleep 2
fullBackup $WORLD
sendCommand $WORLD "save-on"
sendCommand $WORLD "say Backup complete."
else
fullBackup $WORLD
fi
done
printf "\n"
;;
update)
printf "Updating the Minecraft Server software...\n"
# Check for the optional package command line argument.
if [ -n "$2" ] && [ $(listContains $2 "$AVAILABLE_PACKAGES") = 1 ]; then
UPDATE_PACKAGES="$2"
elif [ -n "$2" ]; then
printf "Minecraft software package $2 not found!\n"
printf " Usage: $0 $1 <software package>\n"
exit 1
fi
# If the server software is being updated, stop all the world servers, and backup the worlds.
if [ -n "$(echo \"$UPDATE_PACKAGES\" | grep $SERVER_TYPE)" ]; then
printf "Stopping Minecraft Server:"
for WORLD in $WORLDS; do
if [ $(serverRunning $WORLD) = 1 ]; then
printf " $WORLD"
sendCommand $WORLD "say The server software is being updated."
sendCommand $WORLD "say Server restart is imminent."
sendCommand $WORLD "save-all"
sendCommand $WORLD "save-off"
sendCommand $WORLD "say Restarting in 5 seconds."
sleep 5
stop $WORLD
fi
done
printf "\n"
printf "Backing up Minecraft Server:"
for WORLD in $WORLDS; do
printf " $WORLD"
fullBackup $WORLD
done
printf "\n"
fi
# Update each software package requested.
printf "Updating software package:"
for PACKAGE in $UPDATE_PACKAGES; do
printf " $PACKAGE"
update $PACKAGE
done
printf "\n"
if [ -n "$(echo \"$UPDATE_PACKAGES\" | grep $SERVER_TYPE)" ]; then
printf "Starting Minecraft Server:"
for WORLD in $WORLDS; do
printf " $WORLD"
start $WORLD
done
printf "\n"
fi
;;
c10t|map)
# Make sure that the c10t software exists.
if [ ! -e $C10T_BIN ]; then
printf "c10t software not found, downloading it...\n"
update "c10t"
fi
# Check for the optional world command line argument.
if [ -n "$2" ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
WORLDS="$2"
elif [ -n "$2" ]; then
printf "Minecraft world $2 not found!\n"
printf " Usage: $0 $1 <world>\n"
exit 1
fi
# Run c10t on each world requested.
printf "Running c10t mapping:"
for WORLD in $WORLDS; do
printf " $WORLD"
if [ $(serverRunning $WORLD) = 1 ]; then
sendCommand $WORLD "say The world is about to be mapped with c10t."
sendCommand $WORLD "save-all"
sendCommand $WORLD "save-off"
sleep 20
fullBackup $WORLD
c10t $WORLD
sendCommand $WORLD "save-on"
sendCommand $WORLD "say Mapping is complete. You can access the maps at:"
sendCommand $WORLD "say $MAPS_URL/$WORLD"
else
fullBackup $WORLD
c10t $WORLD
fi
done
printf "\n"
;;
*)
printf "Usage: $0 {start|stop|force-stop|restart|force-restart|status|send|screen|watch|backup|update|c10t} {Optional: world or software package}\n"
exit 1
;;
esac
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment