Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #! /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.
- # 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
- # server - Minecraft server software.
- # c10t - Mapping software.
- ### END INIT INFO
- USER_NAME=minecraft
- LOCATION="/home/$USER_NAME"
- ## Minecraft software options.
- # Software packages, used for updating.
- PACKAGES="server c10t"
- # Minecraft server.
- SERVER_URL="http://www.minecraft.net/download/minecraft_server.jar"
- SERVER_LOCATION="$LOCATION/minecraft_server"
- SERVER_JAR="$SERVER_LOCATION/minecraft_server.jar"
- SERVER_ARGS="nogui"
- INITIAL_MEMORY="1024M"
- MAXIMUM_MEMORY="1024M"
- # c10t mapping software.
- ARCH=$(uname -m)
- C10T_URL="http://toolchain.eu/hudson/job/c10t%20HEAD%20Linux%20$ARCH/lastStableBuild/artifact/build/c10t-HEAD-linux-$ARCH.tar.gz"
- 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://minecraft.server.com/maps"
- MAPS_LOCATION="$LOCATION/maps"
- ## 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"
- ## Backup configuration.
- BACKUP_LOCATION="$LOCATION/backups"
- # Length in days that backups survive.
- BACKUP_FULL_DURATION=31
- ## Internal Methods.
- getProcessIDs() {
- # Get the PIDs of the Screen and Java process for the world server.
- # ARGS: world
- local SCREEN_PID JAVA_PID
- SCREEN_PID=$(su -c "$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")
- su -c "$SCREEN -S minecraft-$1 -p 0 -X stuff \"$COMMAND\"" $USER_NAME
- if [ ! $? = 0 ]; then
- printf "Error sending command to server.\n"
- exit 1
- fi
- }
- listContains() {
- # Check whether a list contains something that matches the pattern.
- # ARGS: pattern list
- local MATCH
- MATCH=$(echo \"$2\" | $PERL -ne 'if ($_ =~ /('$1')/) { print "$1"; }')
- if [ -n "$MATCH" ]; then
- echo 1
- else
- echo 0
- fi
- }
- start() {
- # Start the world server.
- # ARGS: world
- local SERVER_PORT
- # Make sure that the server directory exists.
- su -c "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=$(grep $1 $WORLDS_CONF | cut -f2)
- su -c "printf \"# Minecraft server properties\n\" > server.properties" $USER_NAME
- su -c "printf \"level-name=world\n\" >> server.properties" $USER_NAME
- su -c "printf \"server-port=$SERVER_PORT\n\" >> server.properties" $USER_NAME
- fi
- # Start the server.
- su -c "$SCREEN -dmS minecraft-$1 $JAVA -Xms$INITIAL_MEMORY -Xmx$MAXIMUM_MEMORY -jar $SERVER_JAR $SERVER_ARGS" $USER_NAME
- if [ ! $? = 0 ]; then
- printf "Error starting the server.\n"
- exit 1
- fi
- }
- forceStop() {
- # Forcibly stop the world server.
- # ARGS: world
- local PIDS
- PIDS=$(getProcessIDs $1)
- # Try to stop the server cleanly first.
- sendCommand $1 "stop"
- sleep 5
- # Kill the process ids of the world server.
- kill -9 $PIDS > /dev/null 2>&1
- }
- fullBackup() {
- # Backup the world server.
- # ARGS: world
- # Grab the date and time.
- local DATE_TIME
- DATE_TIME=$(date +%Y-%m-%d-%H:%M:%S)
- su -c "mkdir -p $BACKUP_LOCATION" $USER_NAME
- cd $WORLDS_LOCATION
- su -c "tar -czf $BACKUP_LOCATION/fullBackup-$1-$DATE_TIME.tar.gz $1" $USER_NAME
- # Cleanup old backups.
- su -c "find $BACKUP_LOCATION -name fullBackup-$1-* -type f -mtime +$BACKUP_FULL_DURATION -delete" $USER_NAME
- }
- update() {
- # Update software package.
- # ARGS: package
- case "$1" in
- server)
- su -c "mkdir -p $SERVER_LOCATION" $USER_NAME
- # Backup the old server jar.
- if [ -e $SERVER_JAR ]; then
- su -c "mv -f $SERVER_JAR $SERVER_JAR.old" $USER_NAME
- fi
- # Download the new server software.
- su -c "$WGET -qO $SERVER_JAR $SERVER_URL" $USER_NAME
- # Check for error and restore backup if found.
- if [ ! $? = 0 ]; then
- printf "Error updating server software.\n"
- if [ -e "$SERVER_JAR.old" ]; then
- su -c "mv -f $SERVER_JAR.old $SERVER_JAR" $USER_NAME
- fi
- exit 1
- fi
- ;;
- c10t)
- su -c "mkdir -p $C10T_LOCATION" $USER_NAME
- # Download the new c10t mapping software.
- cd $C10T_LOCATION
- su -c "$WGET -qO c10t.tar.gz $C10T_URL" $USER_NAME
- if [ ! $? = 0 ]; then
- printf "Error updating c10t.\n"
- exit 1
- fi
- su -c "tar xzf c10t.tar.gz" $USER_NAME
- su -c "cp -R c10t-HEAD/* ." $USER_NAME
- su -c "rm -R c10t-HEAD" $USER_NAME
- ;;
- *)
- printf "Unknown software package: $1\n"
- exit 1
- ;;
- esac
- }
- c10t() {
- # Run c10t mapping software on the server.
- # ARGS: world
- su -c "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
- su -c "$C10T_BIN -s -w $WORLDS_LOCATION/$1/world -o $MAPS_LOCATION/$1/surface.png" $USER_NAME
- su -c "$C10T_BIN -s -c -w $WORLDS_LOCATION/$1/world -o $MAPS_LOCATION/$1/caves.png" $USER_NAME
- su -c "$C10T_BIN -s -c -H -w $WORLDS_LOCATION/$1/world -o $MAPS_LOCATION/$1/caves_heightmap.png" $USER_NAME
- su -c "$C10T_BIN -s -a -i 56 -H -w $WORLDS_LOCATION/$1/world -o $MAPS_LOCATION/$1/diamonds_heightmap.png" $USER_NAME
- su -c "$C10T_BIN -s -a -i 4 -H -w $WORLDS_LOCATION/$1/world -o $MAPS_LOCATION/$1/cobble_heightmap.png" $USER_NAME
- su -c "$C10T_BIN -s -q -w $WORLDS_LOCATION/$1/world -o $MAPS_LOCATION/$1/surface_oblique.png" $USER_NAME
- su -c "$C10T_BIN -s -q -c -w $WORLDS_LOCATION/$1/world -o $MAPS_LOCATION/$1/caves_oblique.png" $USER_NAME
- fi
- }
- ## Begin.
- # Make sure that Java, Perl, GNU Screen, and GNU Wget are installed.
- JAVA=$(which java)
- PERL=$(which perl)
- SCREEN=$(which screen)
- WGET=$(which wget)
- if [ ! -e $JAVA ]; then
- printf "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 "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 "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 "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, print a sane error if not.
- if [ ! -n "$(grep $USER_NAME /etc/passwd)" ]; then
- printf "This script requires that a user account named $USER_NAME exist on this system.\n"
- printf "Try adding this user:\n"
- printf "sudo adduser $USER_NAME\n"
- exit 1
- fi
- # From here on out the script needs to be run as root, print a sane error if running as a user.
- WHOAMI=$(whoami)
- if [ ! "$WHOAMI" = "root" ]; then
- printf "This script needs to be run as root, you seem to be $WHOAMI.\n"
- printf "Try running this with sudo:\n"
- printf "sudo $0 start\n"
- exit 1
- fi
- # Make sure that the worlds.conf file exists.
- if [ ! -e $WORLDS_CONF ]; then
- su -c "printf \"$DEFAULT_WORLD\t$DEFAULT_PORT\n\" > $WORLDS_CONF" $USER_NAME
- fi
- # Grab the list of worlds.
- WORLDS=$(cut -f1 $WORLDS_CONF)
- # Respond to the command line arguments.
- case "$1" in
- start)
- printf "Starting Minecraft Server:"
- # Make sure that the server software exists.
- if [ ! -e $SERVER_JAR ]; then
- printf "Server software not found, downloading it...\n"
- update "server"
- 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.
- for WORLD in $WORLDS; do
- if [ $(serverRunning $WORLD) = 0 ]; then
- printf " $WORLD"
- start $WORLD
- fi
- done
- printf "\n"
- ;;
- stop|force-stop)
- printf "Stopping Minecraft Server:"
- # 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.
- 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
- sendCommand $WORLD "stop"
- fi
- sleep 5
- fi
- done
- printf "\n"
- ;;
- restart|reload|force-restart|force-reload)
- printf "Restarting Minecraft Server:"
- # 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.
- 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
- sendCommand $WORLD "stop"
- fi
- sleep 5
- fi;
- start $WORLD
- done
- printf "\n"
- ;;
- status|show)
- printf "Minecraft Server Status:\n"
- # 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.
- for WORLD in $WORLDS; do
- printf " $WORLD: "
- if [ $(serverRunning $WORLD) = 1 ]; then
- printf "running.\n"
- else
- printf "not running.\n"
- fi
- done
- ;;
- send)
- WORLD=$2
- if [ -n "$WORLD" ] && [ $(listContains $WORLD "$WORLDS") = 1 ]; then
- shift 2
- printf "Send command to world $WORLD: $*\n"
- sendCommand $WORLD "$*"
- else
- printf "Minecraft world $WORLD not found!\n"
- printf " Usage: $0 $1 <world> <command>\n"
- printf " ie: $0 $1 world say \"Hello World!\"\n"
- exit 1
- fi
- ;;
- backup)
- printf "Backing up Minecraft Server:"
- # 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.
- 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 20
- 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 "$PACKAGES") = 1 ]; then
- 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 [ -n "$(echo $PACKAGES | grep server)" ]; then
- printf "Stopping Minecraft Server:"
- for WORLD in $WORLDS; do
- printf " $WORLD"
- if [ $(serverRunning $WORLD) = 1 ]; then
- sendCommand $WORLD "say The server software is being updated."
- sendCommand $WORLD "say Server restart is imminent."
- sendCommand $WORLD "save-all"
- sendCommand $WORLD "save-off"
- sleep 20
- fullBackup $WORLD
- sendCommand $WORLD "say Restarting in 5 seconds."
- sleep 5
- sendCommand $WORLD "stop"
- else
- fullBackup $WORLD
- fi
- done
- printf "\n"
- fi
- # Update each software package requested.
- printf "Updating software package:"
- for PACKAGE in $PACKAGES; do
- printf " $PACKAGE"
- update $PACKAGE
- done
- printf "\n"
- if [ -n "$(echo $PACKAGES | grep server)" ]; 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|backup|update|c10t} {Optional: world or software package}\n"
- exit 1
- ;;
- esac
- exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement