├── README.md ├── monitor └── CheckServer │ └── CheckServer.java └── script └── minecraft /README.md: -------------------------------------------------------------------------------- 1 | Disclaimer: These files will not automatically work with your server. They are simply posted for those curious how the script works. These work for our specific and highly customized server, and if you want to use them you will need to adapt these scripts to work for your environment. 2 | 3 | We provide no warranty or support with these files. If you muck up yours or your friend's server we are not responsible. 4 | 5 | User discretion is advised. 6 | -------------------------------------------------------------------------------- /monitor/CheckServer/CheckServer.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.net.*; 3 | 4 | public class CheckServer { 5 | public static void main(String[] args) { 6 | if (args.length < 2) 7 | { 8 | System.out.println("Usage: CheckServer "); 9 | System.exit(1); 10 | } 11 | String host = args[0]; 12 | int port = Integer.parseInt(args[1]); 13 | 14 | int failCount = 0; 15 | 16 | for (;;) { 17 | Socket socket = null; 18 | DataInputStream datainputstream = null; 19 | DataOutputStream dataoutputstream = null; 20 | 21 | try { 22 | socket = new Socket(); 23 | 24 | socket.setSoTimeout(3000); 25 | socket.setTcpNoDelay(true); 26 | socket.setTrafficClass(18); 27 | 28 | socket.connect(new InetSocketAddress(host, port), 3000); 29 | 30 | datainputstream = new DataInputStream(socket.getInputStream()); 31 | dataoutputstream = new DataOutputStream(socket.getOutputStream()); 32 | 33 | dataoutputstream.write(254); 34 | 35 | if (datainputstream.read() != 255) throw new IOException("Bad message"); 36 | 37 | short strLength = datainputstream.readShort(); 38 | if (strLength < 0 || strLength > 64) throw new IOException("invalid string length"); 39 | 40 | StringBuilder stringBuilder = new StringBuilder(); 41 | for(int i=0; i= 10) { 66 | try { 67 | //System.out.println("Restart"); 68 | String command[] = { "/bin/bash", "service", "minecraft", "restart" }; 69 | 70 | Process restartProcess = Runtime.getRuntime().exec(command); 71 | restartProcess.waitFor(); 72 | 73 | Thread.sleep(60000); 74 | } catch (Exception e2) { 75 | return; 76 | } 77 | } 78 | } finally { 79 | try { 80 | if(datainputstream != null) datainputstream.close(); 81 | } catch(Throwable throwable) { } 82 | try { 83 | if(dataoutputstream != null) dataoutputstream.close(); 84 | } catch(Throwable throwable1) { } 85 | try { 86 | if(socket != null) socket.close(); 87 | } catch(Throwable throwable2) { } 88 | } 89 | 90 | try { 91 | Thread.sleep(30000); 92 | } catch (Exception e) { } 93 | } 94 | } 95 | } 96 | 97 | -------------------------------------------------------------------------------- /script/minecraft: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # /etc/init.d/minecraft 3 | # version 0.3.2 2011-01-27 (YYYY-MM-DD) 4 | 5 | ### BEGIN INIT INFO 6 | # Provides: minecraft 7 | # Required-Start: $local_fs $remote_fs 8 | # Required-Stop: $local_fs $remote_fs 9 | # Should-Start: $network 10 | # Should-Stop: $network 11 | # Default-Start: 2 3 4 5 12 | # Default-Stop: 0 1 6 13 | # Short-Description: Minecraft server 14 | # Description: Starts the minecraft server 15 | ### END INIT INFO 16 | 17 | # Settings start 18 | USERNAME="" 19 | JMXPORT= 20 | 21 | SERVICE='forge_latest.zip' 22 | MCPATH="/home/$USERNAME/minecraft" 23 | BACKUPPATH="/home/$USERNAME/backup" 24 | CHECKSERVER="/home/$USERNAME/CheckServer" 25 | JMXPWFILE="" 26 | CRASHLOG_DB_PATH='' 27 | JAVA_HOME="/usr/local/lib/jrockit" 28 | 29 | MEMORY_OPTS="-Xmx8G -Xms8G" 30 | JAVA_OPTIONS="-XX:FlightRecorderOptions=defaultrecording=true,disk=true,repository=/home/$USERNAME/jfr/,maxage=30m,settings=profile" 31 | JMX_OPTIONS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=$JMXPORT -Dcom.sun.management.jmxremote.password.file=$JMXPWFILE" 32 | 33 | INVOCATION="${JAVA_HOME}/bin/java ${MEMORY_OPTS} ${JAVA_OPTIONS} ${JMX_OPTIONS} -jar $SERVICE nogui" 34 | BACKUPARCHIVEPATH=$BACKUPPATH/archive 35 | BACKUPDIR=$(date +%b_%Y) 36 | PORT=$(grep server-port $MCPATH/server.properties | cut -d '=' -f 2) 37 | 38 | if [ -z "$PORT" ]; then 39 | PORT=25565 40 | fi 41 | 42 | # Settings end 43 | 44 | if [ $(whoami) != $USERNAME ]; then 45 | su $USERNAME -l -c "$(readlink -f $0) $*" 46 | exit $? 47 | fi 48 | 49 | is_running() { 50 | if [ ! -e $MCPATH/java.pid ]; then 51 | return 1 52 | fi 53 | 54 | pid=$(cat $MCPATH/java.pid) 55 | if [ -z $pid ]; then 56 | return 1 57 | fi 58 | 59 | ps -eo "%p" | grep "^\\s*$pid\\s*\$" > /dev/null 60 | return $? 61 | } 62 | 63 | mc_start() { 64 | if is_running; then 65 | echo "Tried to start but $SERVICE was already running!" 66 | else 67 | echo "$SERVICE was not running... starting." 68 | 69 | cd $MCPATH 70 | screen -dmS mc$PORT $INVOCATION & 71 | 72 | for (( i=0; i < 10; i++ )); do 73 | screenpid=$(ps -eo '%p %a' | grep -v grep | grep -i screen | grep mc$PORT | awk '{print $1}') 74 | javapid=$(ps -eo '%P %p' | grep "^\\s*$screenpid " | awk '{print $2}') 75 | 76 | if [[ -n "$screenpid" && -n "$javapid" ]]; then 77 | break 78 | fi 79 | 80 | sleep 1 81 | done 82 | 83 | if [[ -n "$screenpid" && -n "$javapid" ]]; then 84 | echo "$SERVICE is now running." 85 | echo "$javapid" > $MCPATH/java.pid 86 | echo "$screenpid.mc$PORT" > $MCPATH/screen.name 87 | else 88 | echo "Could not start $SERVICE." 89 | fi 90 | fi 91 | } 92 | 93 | mc_startmonitor() { 94 | if [ -z $CHECKSERVER ]; then 95 | echo "started monitor" 96 | /usr/bin/daemon --name=minecraft_checkserver -- $JAVA_HOME/bin/java -cp $CHECKSERVER CheckServer localhost $PORT 97 | fi 98 | } 99 | 100 | mc_saveoff() { 101 | if is_running; then 102 | echo "$SERVICE is running... suspending saves" 103 | mc_exec "say SERVER BACKUP STARTING. Server going readonly..." 104 | mc_exec "save-off" 105 | mc_exec "save-all" 106 | sync 107 | sleep 10 108 | else 109 | echo "$SERVICE was not running. Not suspending saves." 110 | fi 111 | } 112 | 113 | mc_saveon() { 114 | if is_running; then 115 | echo "$SERVICE is running... re-enabling saves" 116 | mc_exec "save-on" 117 | mc_exec "say SERVER BACKUP ENDED. Server going read-write..." 118 | else 119 | echo "$SERVICE was not running. Not resuming saves." 120 | fi 121 | } 122 | 123 | mc_kill() { 124 | pid=$(cat $MCPATH/java.pid) 125 | 126 | echo "terminating process with pid $pid" 127 | kill $pid 128 | 129 | for (( i=0; i < 10; i++ )); do 130 | is_running || break 131 | sleep 1 132 | done 133 | 134 | if is_running; then 135 | echo "$SERVICE could not be terminated, killing..." 136 | kill -SIGKILL $pid 137 | echo "$SERVICE killed" 138 | else 139 | echo "$SERVICE terminated" 140 | fi 141 | } 142 | 143 | mc_stop() { 144 | if is_running; then 145 | echo "$SERVICE is running... stopping." 146 | 147 | mc_exec "say SERVER SHUTTING DOWN IN 10 SECONDS. Saving map..." 148 | mc_exec "save-all" 149 | sleep 10 150 | mc_exec "stop" 151 | 152 | for (( i=0; i < 20; i++ )); do 153 | is_running || break 154 | sleep 1 155 | done 156 | else 157 | echo "$SERVICE was not running." 158 | fi 159 | 160 | if is_running; then 161 | echo "$SERVICE could not be shut down cleanly... still running." 162 | mc_kill 163 | else 164 | echo "$SERVICE is shut down." 165 | fi 166 | 167 | rm $MCPATH/java.pid 168 | rm $MCPATH/screen.name 169 | } 170 | 171 | mc_stopmonitor() { 172 | if [ -z $CHECKSERVER ]; then 173 | /usr/bin/daemon --name=minecraft_checkserver --stop 174 | fi 175 | } 176 | 177 | mc_backup() { 178 | echo "Backing up minecraft world" 179 | 180 | [ -d "$BACKUPPATH/$BACKUPDIR" ] || mkdir -p "$BACKUPPATH/$BACKUPDIR" 181 | 182 | rdiff-backup $MCPATH "$BACKUPPATH/$BACKUPDIR" 183 | 184 | echo "Backup complete" 185 | } 186 | 187 | mc_thinoutbackup() { 188 | if (($(date +%H) == 0)) && (($(date +%M) < 15)); then 189 | archivedate=$(date --date="7 days ago") 190 | 191 | echo "Thinning backups created $archivedate out" 192 | 193 | archivedateunix=$(date --date="$archivedate" +%s) 194 | archivesourcedir=$BACKUPPATH/$(date --date="$archivedate" +%b_%Y) 195 | archivesource=$archivesourcedir/rdiff-backup-data/increments.$(date --date="$archivedate" +%Y-%m-%dT%H):0*.dir 196 | archivesource=$(echo $archivesource) 197 | archivedest=$BACKUPARCHIVEPATH/$(date --date="$archivedate" +%b_%Y) 198 | 199 | if [[ ! -f $archivesource ]]; then 200 | echo "Nothing to be done" 201 | else 202 | tempdir=$(mktemp -d) 203 | 204 | if [[ ! $tempdir =~ ^/tmp ]]; then 205 | echo "invalid tmp dir $tempdir" 206 | else 207 | rdiff-backup $archivesource $tempdir 208 | rdiff-backup --current-time $archivedateunix $tempdir $archivedest 209 | rm -R "$tempdir" 210 | 211 | rdiff-backup --remove-older-than 7D --force $archivesourcedir 212 | 213 | echo "done" 214 | fi 215 | fi 216 | fi 217 | } 218 | 219 | mc_exec() { 220 | if is_running; then 221 | screen -p 0 -S $(cat $MCPATH/screen.name) -X stuff "$@$(printf \\r)" 222 | else 223 | echo "$SERVICE was not running. Not executing command." 224 | fi 225 | } 226 | 227 | mc_dumpcrashlogs() { 228 | if is_running; then 229 | cp $MCPATH/crash-reports/* $CRASHLOG_DB_PATH 230 | mv $MCPATH/crash-reports/* $MCPATH/crash-reports.archive/ 231 | fi 232 | } 233 | 234 | #Start-Stop here 235 | case "$1" in 236 | start) 237 | if mc_start 238 | then 239 | mc_startmonitor 240 | fi 241 | ;; 242 | stop) 243 | mc_stopmonitor 244 | mc_stop 245 | ;; 246 | restart) 247 | mc_stop 248 | mc_start 249 | ;; 250 | backup) 251 | mc_saveoff 252 | mc_backup 253 | mc_saveon 254 | mc_thinoutbackup 255 | ;; 256 | exec) 257 | shift 258 | mc_exec "$@" 259 | ;; 260 | dumpcrashlogs) 261 | mc_dumpcrashlogs 262 | ;; 263 | status) 264 | if is_running 265 | then 266 | echo "$SERVICE is running." 267 | else 268 | echo "$SERVICE is not running." 269 | fi 270 | ;; 271 | 272 | *) 273 | echo "Usage: $(readlink -f $0) {start|stop|restart|backup|exec|dumpcrashlogs|status}" 274 | exit 1 275 | ;; 276 | esac 277 | 278 | exit 0 279 | --------------------------------------------------------------------------------