Advertisement
Guest User

Untitled

a guest
Jan 16th, 2011
559
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 15.87 KB | None | 0 0
  1. #! /bin/sh
  2. ### BEGIN INIT INFO
  3. # Provides:          minecraft_server
  4. # Required-Start:    $remote_fs $syslog
  5. # Required-Stop:     $remote_fs $syslog
  6. # Default-Start:     2 3 4 5
  7. # Default-Stop:      0 1 6
  8. # Short-Description: Minecraft Server control script.
  9. # Description:       Minecraft Server control script.
  10. #   Options
  11. #     start <world>          - Start the Minecraft world server.  Starts all world servers by default.
  12. #     stop <world>           - Stop the Minecraft world server.  Stops all world servers by default.
  13. #     force-stop <world>     - Forcibly stop the Minecraft world server.  Forcibly stops all world servers by default.
  14. #     restart <world>        - Restart the Minecraft world server.  Restarts all world servers by default.
  15. #     force-restart <world>  - Forcibly restart the Minecraft world server.  Forcibly restarts all world servers by default.
  16. #     status <world>         - Display the status of the Minecraft world server.  Displays the status of all world servers by default.
  17. #     send <world> <command> - Send a command to a Minecraft world server.
  18. #     backup <world>         - Backup the Minecraft world.  Backup all worlds by default.
  19. #     c10t <world>           - Run the c10t mapping software on the Minecraft world.  Maps all worlds by default.
  20. #     update <software>      - Update a software package.  Update the server software and all addons by default.
  21. #                                Available software options
  22. #                                  server - Minecraft server software.
  23. #                                  c10t - Mapping software.
  24. ### END INIT INFO
  25.  
  26.  
  27. USER_NAME=minecraft
  28.  
  29. LOCATION="/home/$USER_NAME"
  30.  
  31.  
  32. ## Minecraft software options.
  33.  
  34. # Software packages, used for updating.
  35. PACKAGES="server c10t"
  36.  
  37. # Minecraft server.
  38. SERVER_URL="http://www.minecraft.net/download/minecraft_server.jar"
  39. SERVER_LOCATION="$LOCATION/minecraft_server"
  40. SERVER_JAR="$SERVER_LOCATION/minecraft_server.jar"
  41. SERVER_ARGS="nogui"
  42. INITIAL_MEMORY="1024M"
  43. MAXIMUM_MEMORY="1024M"
  44.  
  45. # c10t mapping software.
  46. ARCH=$(uname -m)
  47. C10T_URL="http://toolchain.eu/hudson/job/c10t%20HEAD%20Linux%20$ARCH/lastStableBuild/artifact/build/c10t-HEAD-linux-$ARCH.tar.gz"
  48. C10T_LOCATION="$LOCATION/c10t"
  49. C10T_BIN="$C10T_LOCATION/c10t"
  50.  
  51. # Location to place map images, and the URL displayed to users for map access.
  52. MAPS_URL="http://minecraft.server.com/maps"
  53. MAPS_LOCATION="$LOCATION/maps"
  54.  
  55.  
  56. ## World configuration.
  57.  
  58. WORLDS_LOCATION="$LOCATION/worlds"
  59.  
  60. # List of worlds and the ports they are running on.  This file will
  61. # be generated if missing.
  62. # Note: World name should not contain a space, at least for now.
  63. # ie:
  64. #   alpha   25565
  65. #   beta    25566
  66. WORLDS_CONF="$LOCATION/worlds.conf"
  67.  
  68. # Default world name and port if worlds.conf is missing.
  69. DEFAULT_WORLD="world"
  70. DEFAULT_PORT="25565"
  71.  
  72.  
  73. ## Backup configuration.
  74.  
  75. BACKUP_LOCATION="$LOCATION/backups"
  76.  
  77. # Length in days that backups survive.
  78. BACKUP_FULL_DURATION=31
  79.  
  80.  
  81. ## Internal Methods.
  82.  
  83. getProcessIDs() {
  84.     # Get the PIDs of the Screen and Java process for the world server.
  85.     # ARGS: world
  86.     local SCREEN_PID JAVA_PID
  87.     SCREEN_PID=$(su -c "$SCREEN -ls" $USER_NAME | $PERL -ne 'if ($_ =~ /^\t(\d+)\.minecraft-'$1'/) { print $1; }')
  88.     JAVA_PID=$(ps -a -u $USER_NAME -o pid,ppid,comm | $PERL -ne 'if ($_ =~ /^\s*(\d+)\s+'$SCREEN_PID'\s+java/) { print $1; }')
  89.     echo "$SCREEN_PID $JAVA_PID"
  90. }
  91.  
  92. serverRunning() {
  93.     # Check to see if the world server is running.
  94.     # ARGS: world
  95.     local PIDS
  96.     PIDS=$(getProcessIDs $1)
  97.     # Try to determine if the world is running.
  98.     if [ -n "$(echo $PIDS | cut -d ' ' -f1)" ] && [ -n "$(echo $PIDS | cut -d ' ' -f2)" ]; then
  99.         echo 1
  100.     else
  101.         echo 0
  102.     fi
  103. }
  104.  
  105. sendCommand() {
  106.     # Send a command to the world server.
  107.     # ARGS: world command
  108.     local COMMAND
  109.     COMMAND=$(printf "$2\r")
  110.     su -c "$SCREEN -S minecraft-$1 -p 0 -X stuff \"$COMMAND\"" $USER_NAME
  111.     if [ ! $? = 0 ]; then
  112.         printf "Error sending command to server.\n"
  113.         exit 1
  114.     fi
  115.  
  116. }
  117.  
  118. listContains() {
  119.     # Check whether a list contains something that matches the pattern.
  120.     # ARGS: pattern list
  121.     local MATCH
  122.     MATCH=$(echo \"$2\" | $PERL -ne 'if ($_ =~ /('$1')/) { print "$1"; }')
  123.     if [ -n "$MATCH" ]; then
  124.         echo 1
  125.     else
  126.         echo 0
  127.     fi
  128. }
  129.  
  130. start() {
  131.     # Start the world server.
  132.     # ARGS: world
  133.     local SERVER_PORT
  134.     # Make sure that the server directory exists.
  135.     su -c "mkdir -p $WORLDS_LOCATION/$1" $USER_NAME
  136.     cd $WORLDS_LOCATION/$1
  137.     # Make sure that the server properties file exists.
  138.     if [ ! -e server.properties ]; then
  139.         SERVER_PORT=$(grep $1 $WORLDS_CONF | cut -f2)
  140.         su -c "printf \"# Minecraft server properties\n\" > server.properties" $USER_NAME
  141.         su -c "printf \"level-name=world\n\" >> server.properties" $USER_NAME
  142.         su -c "printf \"server-port=$SERVER_PORT\n\" >> server.properties" $USER_NAME
  143.     fi
  144.     # Start the server.
  145.     su -c "$SCREEN -dmS minecraft-$1 $JAVA -Xms$INITIAL_MEMORY -Xmx$MAXIMUM_MEMORY -jar $SERVER_JAR $SERVER_ARGS" $USER_NAME
  146.     if [ ! $? = 0 ]; then
  147.         printf "Error starting the server.\n"
  148.         exit 1
  149.     fi
  150. }
  151.  
  152. forceStop() {
  153.     # Forcibly stop the world server.
  154.     # ARGS: world
  155.     local PIDS
  156.     PIDS=$(getProcessIDs $1)
  157.     # Try to stop the server cleanly first.
  158.     sendCommand $1 "stop"
  159.     sleep 5
  160.     # Kill the process ids of the world server.
  161.     kill -9 $PIDS > /dev/null 2>&1
  162. }
  163.  
  164. fullBackup() {
  165.     # Backup the world server.
  166.     # ARGS: world
  167.     # Grab the date and time.
  168.     local DATE_TIME
  169.     DATE_TIME=$(date +%Y-%m-%d-%H:%M:%S)
  170.     su -c "mkdir -p $BACKUP_LOCATION" $USER_NAME
  171.     cd $WORLDS_LOCATION
  172.     su -c "tar -czf $BACKUP_LOCATION/fullBackup-$1-$DATE_TIME.tar.gz $1" $USER_NAME
  173.     # Cleanup old backups.
  174.     su -c "find $BACKUP_LOCATION -name fullBackup-$1-* -type f -mtime +$BACKUP_FULL_DURATION -delete" $USER_NAME
  175. }
  176.  
  177. update() {
  178.     # Update software package.
  179.     # ARGS: package
  180.     case "$1" in
  181.         server)
  182.             su -c "mkdir -p $SERVER_LOCATION" $USER_NAME
  183.             # Backup the old server jar.
  184.             if [ -e $SERVER_JAR ]; then
  185.                 su -c "mv -f $SERVER_JAR $SERVER_JAR.old" $USER_NAME
  186.             fi
  187.             # Download the new server software.
  188.             su -c "$WGET -qO $SERVER_JAR $SERVER_URL" $USER_NAME
  189.             # Check for error and restore backup if found.
  190.             if [ ! $? = 0 ]; then
  191.                 printf "Error updating server software.\n"
  192.                 if [ -e "$SERVER_JAR.old" ]; then
  193.                     su -c "mv -f $SERVER_JAR.old $SERVER_JAR" $USER_NAME
  194.                 fi
  195.                 exit 1
  196.             fi
  197.         ;;
  198.         c10t)
  199.             su -c "mkdir -p $C10T_LOCATION" $USER_NAME
  200.             # Download the new c10t mapping software.
  201.             cd $C10T_LOCATION
  202.             su -c "$WGET -qO c10t.tar.gz $C10T_URL" $USER_NAME
  203.             if [ ! $? = 0 ]; then
  204.                 printf "Error updating c10t.\n"
  205.                 exit 1
  206.             fi
  207.             su -c "tar xzf c10t.tar.gz" $USER_NAME
  208.             su -c "cp -R c10t-HEAD/* ." $USER_NAME
  209.             su -c "rm -R c10t-HEAD" $USER_NAME
  210.         ;;
  211.         *)
  212.             printf "Unknown software package: $1\n"
  213.             exit 1
  214.         ;;
  215.     esac
  216. }
  217.  
  218. c10t() {
  219.     # Run c10t mapping software on the server.
  220.     # ARGS: world
  221.     su -c "mkdir -p $MAPS_LOCATION/$1" $USER_NAME
  222.     # Make sure that the world files are actually there before mapping.
  223.     if [ -e "$WORLDS_LOCATION/$1/server.properties" ]; then
  224.         su -c "$C10T_BIN -s -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/surface.png" $USER_NAME
  225.         su -c "$C10T_BIN -s -c -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/caves.png" $USER_NAME
  226.         su -c "$C10T_BIN -s -c -H -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/caves_heightmap.png" $USER_NAME
  227.         su -c "$C10T_BIN -s -a -i 56 -H -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/diamonds_heightmap.png" $USER_NAME
  228.         su -c "$C10T_BIN -s -a -i 4 -H -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/cobble_heightmap.png" $USER_NAME
  229.         su -c "$C10T_BIN -s -q -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/surface_oblique.png" $USER_NAME
  230.         su -c "$C10T_BIN -s -q -c -w $WORLDS_LOCATION/$1/$1 -o $MAPS_LOCATION/$1/caves_oblique.png" $USER_NAME
  231.     fi
  232. }
  233.  
  234. ## Begin.
  235.  
  236. # Make sure that Java, Perl, GNU Screen, and GNU Wget are installed.
  237. JAVA=$(which java)
  238. PERL=$(which perl)
  239. SCREEN=$(which screen)
  240. WGET=$(which wget)
  241. if [ ! -e $JAVA ]; then
  242.     printf "Java not found!\n"
  243.     printf "Try installing this with:\n"
  244.     printf "sudo apt-get install openjdk-6-jre\n"
  245.     exit 1
  246. fi
  247. if [ ! -e $PERL ]; then
  248.     printf "Perl not found!\n"
  249.     printf "Try installing this with:\n"
  250.     printf "sudo apt-get install perl\n"
  251.     exit 1
  252. fi
  253. if [ ! -e $SCREEN ]; then
  254.     printf "GNU Screen not found!\n"
  255.     printf "Try installing this with:\n"
  256.     printf "sudo apt-get install screen\n"
  257.     exit 1
  258. fi
  259. if [ ! -e $WGET ]; then
  260.     printf "GNU Wget not found!\n"
  261.     printf "Try installing this with:\n"
  262.     printf "sudo apt-get install wget\n"
  263.     exit 1
  264. fi
  265.  
  266. # Make sure that the minecraft user exists, print a sane error if not.
  267. if [ ! -n "$(grep $USER_NAME /etc/passwd)" ]; then
  268.     printf "This script requires that a user account named $USER_NAME exist on this system.\n"
  269.     printf "Try adding this user:\n"
  270.     printf "sudo adduser $USER_NAME\n"
  271.     exit 1
  272. fi
  273.  
  274. # From here on out the script needs to be run as root, print a sane error if running as a user.
  275. WHOAMI=$(whoami)
  276. if [ ! "$WHOAMI" = "root" ]; then
  277.     printf "This script needs to be run as root, you seem to be $WHOAMI.\n"
  278.     printf "Try running this with sudo:\n"
  279.     printf "sudo $0 start\n"
  280.     exit 1
  281. fi
  282.  
  283. # Make sure that the worlds.conf file exists.
  284. if [ ! -e $WORLDS_CONF ]; then
  285.     su -c "printf \"$DEFAULT_WORLD\t$DEFAULT_PORT\n\" > $WORLDS_CONF" $USER_NAME
  286. fi
  287.  
  288. # Grab the list of worlds.
  289. WORLDS=$(cut -f1 $WORLDS_CONF)
  290.  
  291. # Respond to the command line arguments.
  292. case "$1" in
  293.     start)
  294.         printf "Starting Minecraft Server:"
  295.         # Make sure that the server software exists.
  296.         if [ ! -e $SERVER_JAR ]; then
  297.             printf "Server software not found, downloading it...\n"
  298.             update "server"
  299.         fi
  300.         # Check for the optional world command line argument.
  301.         if [ -n "$2"  ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
  302.             WORLDS="$2"
  303.         elif [ -n "$2" ]; then
  304.             printf "Minecraft world $2 not found!\n"
  305.             printf "  Usage:  $0 $1 <world>\n"
  306.             exit 1
  307.         fi
  308.         # Start each world requested, if not already running.
  309.         for WORLD in $WORLDS; do
  310.             if [ $(serverRunning $WORLD) = 0 ]; then
  311.                 printf " $WORLD"
  312.                 start $WORLD
  313.             fi
  314.         done
  315.         printf "\n"
  316.     ;;
  317.     stop|force-stop)
  318.         printf "Stopping Minecraft Server:"
  319.         # Check for the optional world command line argument.
  320.         if [ -n "$2"  ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
  321.             WORLDS="$2"
  322.         elif [ -n "$2" ]; then
  323.             printf "Minecraft world $2 not found!\n"
  324.             printf "  Usage:  $0 $1 <world>\n"
  325.             exit 1
  326.         fi
  327.         # Stop each world requested, if running.
  328.         for WORLD in $WORLDS; do
  329.             # Try to stop the world cleanly.
  330.             if [ $(serverRunning $WORLD) = 1 ]; then
  331.                 printf " $WORLD"
  332.                 sendCommand $WORLD "say The server is about to go down."
  333.                 sendCommand $WORLD "save-all"
  334.                 sendCommand $WORLD "save-off"
  335.                 sendCommand $WORLD "say The server is going down in 5 seconds..."
  336.                 sleep 5
  337.                 if [ "$1" = "force-stop" ]; then
  338.                     forceStop $WORLD
  339.                 else
  340.                     sendCommand $WORLD "stop"
  341.                 fi
  342.                 sleep 5
  343.             fi
  344.         done
  345.         printf "\n"
  346.     ;;
  347.     restart|reload|force-restart|force-reload)
  348.         printf "Restarting Minecraft Server:"
  349.         # Check for the optional world command line argument.
  350.         if [ -n "$2"  ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
  351.             WORLDS="$2"
  352.         elif [ -n "$2" ]; then
  353.             printf "Minecraft world $2 not found!\n"
  354.             printf "  Usage:  $0 $1 <world>\n"
  355.             exit 1
  356.         fi
  357.         # Restart each world requested, start those not already running.
  358.         for WORLD in $WORLDS; do
  359.             printf " $WORLD"
  360.             if [ $(serverRunning $WORLD) = 1 ]; then
  361.                 sendCommand $WORLD "say The server is about to restart."
  362.                 sendCommand $WORLD "save-all"
  363.                 sendCommand $WORLD "save-off"
  364.                 sendCommand $WORLD "say Restarting in 5 seconds..."
  365.                 sleep 5
  366.                 if [ "$(echo $1 | cut -d '-' -f1)" = "force" ]; then
  367.                     forceStop $WORLD
  368.                 else
  369.                     sendCommand $WORLD "stop"
  370.                 fi
  371.                 sleep 5
  372.             fi;
  373.             start $WORLD
  374.         done
  375.         printf "\n"
  376.     ;;
  377.     status|show)
  378.         printf "Minecraft Server Status:\n"
  379.         # Check for the optional world command line argument.
  380.         if [ -n "$2"  ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
  381.             WORLDS="$2"
  382.         elif [ -n "$2" ]; then
  383.             printf "Minecraft world $2 not found!\n"
  384.             printf "  Usage:  $0 $1 <world>\n"
  385.             exit 1
  386.         fi
  387.         # Show the status of each world requested.
  388.         for WORLD in $WORLDS; do
  389.             printf "  $WORLD: "
  390.             if [ $(serverRunning $WORLD) = 1 ]; then
  391.                 printf "running.\n"
  392.             else
  393.                 printf "not running.\n"
  394.             fi
  395.         done
  396.     ;;
  397.     send)
  398.         WORLD=$2
  399.         if [ -n "$WORLD" ] && [ $(listContains $WORLD "$WORLDS") = 1 ]; then
  400.             shift 2
  401.             printf "Send command to world $WORLD: $*\n"
  402.             sendCommand $WORLD "$*"
  403.         else
  404.             printf "Minecraft world $WORLD not found!\n"
  405.             printf "  Usage:  $0 $1 <world> <command>\n"
  406.             printf "     ie:  $0 $1 world say \"Hello World!\"\n"
  407.             exit 1
  408.         fi
  409.     ;;
  410.     backup)
  411.         printf "Backing up Minecraft Server:"
  412.         # Check for the optional world command line argument.
  413.         if [ -n "$2"  ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
  414.             WORLDS="$2"
  415.         elif [ -n "$2" ]; then
  416.             printf "Minecraft world $2 not found!\n"
  417.             printf "  Usage:  $0 $1 <world>\n"
  418.             exit 1
  419.         fi
  420.         # Backup each world requested.
  421.         for WORLD in $WORLDS; do
  422.             printf " $WORLD"
  423.             if [ $(serverRunning $WORLD) = 1 ]; then
  424.                 sendCommand $WORLD "say Backing up the world."
  425.                 sendCommand $WORLD "save-all"
  426.                 sendCommand $WORLD "save-off"
  427.                 sleep 20
  428.                 fullBackup $WORLD
  429.                 sendCommand $WORLD "save-on"
  430.                 sendCommand $WORLD "say Backup complete."
  431.             else
  432.                 fullBackup $WORLD
  433.             fi
  434.         done
  435.         printf "\n"
  436.     ;;
  437.     update)
  438.         printf "Updating the Minecraft Server software...\n"
  439.         # Check for the optional package command line argument.
  440.         if [ -n "$2"  ] && [ $(listContains $2 "$PACKAGES") = 1 ]; then
  441.             PACKAGES="$2"
  442.         elif [ -n "$2" ]; then
  443.             printf "Minecraft software package $2 not found!\n"
  444.             printf "  Usage:  $0 $1 <software package>\n"
  445.             exit 1
  446.         fi
  447.         if [ -n "$(echo $PACKAGES | grep server)" ]; then
  448.             printf "Stopping Minecraft Server:"
  449.             for WORLD in $WORLDS; do
  450.                 printf " $WORLD"
  451.                 if [ $(serverRunning $WORLD) = 1 ]; then
  452.                     sendCommand $WORLD "say The server software is being updated."
  453.                     sendCommand $WORLD "say Server restart is imminent."
  454.                     sendCommand $WORLD "save-all"
  455.                     sendCommand $WORLD "save-off"
  456.                     sleep 20
  457.                     fullBackup $WORLD
  458.                     sendCommand $WORLD "say Restarting in 5 seconds."
  459.                     sleep 5
  460.                     sendCommand $WORLD "stop"
  461.                 else
  462.                     fullBackup $WORLD
  463.                 fi
  464.             done
  465.             printf "\n"
  466.         fi
  467.         # Update each software package requested.
  468.         printf "Updating software package:"
  469.         for PACKAGE in $PACKAGES; do
  470.             printf " $PACKAGE"
  471.             update $PACKAGE
  472.         done
  473.         printf "\n"
  474.         if [ -n "$(echo $PACKAGES | grep server)" ]; then
  475.             printf "Starting Minecraft Server:"
  476.             for WORLD in $WORLDS; do
  477.                 printf " $WORLD"
  478.                 start $WORLD
  479.             done
  480.             printf "\n"
  481.         fi
  482.     ;;
  483.     c10t|map)
  484.         # Make sure that the c10t software exists.
  485.         if [ ! -e $C10T_BIN ]; then
  486.             printf "c10t software not found, downloading it...\n"
  487.             update "c10t"
  488.         fi
  489.         # Check for the optional world command line argument.
  490.         if [ -n "$2"  ] && [ $(listContains $2 "$WORLDS") = 1 ]; then
  491.             WORLDS="$2"
  492.         elif [ -n "$2" ]; then
  493.             printf "Minecraft world $2 not found!\n"
  494.             printf "  Usage:  $0 $1 <world>\n"
  495.             exit 1
  496.         fi
  497.         # Run c10t on each world requested.
  498.         printf "Running c10t mapping:"
  499.         for WORLD in $WORLDS; do
  500.             printf " $WORLD"
  501.             if [ $(serverRunning $WORLD) = 1 ]; then
  502.                 sendCommand $WORLD "say The world is about to be mapped with c10t."
  503.                 sendCommand $WORLD "save-all"
  504.                 sendCommand $WORLD "save-off"
  505.                 sleep 20
  506.                 fullBackup $WORLD
  507.                 c10t $WORLD
  508.                 sendCommand $WORLD "save-on"
  509.                 sendCommand $WORLD "say Mapping is complete.  You can access the maps at:"
  510.                 sendCommand $WORLD "say $MAPS_URL/$WORLD"
  511.             else
  512.                 fullBackup $WORLD
  513.                 c10t $WORLD
  514.             fi
  515.         done
  516.         printf "\n"
  517.     ;;
  518.     *)
  519.         printf "Usage: $0 {start|stop|force-stop|restart|force-restart|status|send|backup|update|c10t} {Optional: world or software package}\n"
  520.         exit 1
  521.     ;;
  522. esac
  523. exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement