Skip to content

Commit

Permalink
The real initial commit
Browse files Browse the repository at this point in the history
This should be a working copy of the program. The whole reason I was making this repo was because I wanted to add the planned feature I mention in the README, but now it's taken me two hours to prepare the code for public use and I don't feel like it any more ¯\_(ツ)_/¯

Signed-off-by: Rhotias <[email protected]>
  • Loading branch information
Phidica committed Nov 26, 2015
1 parent 19b89fe commit 4b05101
Show file tree
Hide file tree
Showing 5 changed files with 315 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.sublime-workspace
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,41 @@
# mcserver
A collection of Bash and Python scripts to simplify the management of multiple Minecraft servers
A collection of Bash and Python scripts to simplify the management of multiple Minecraft servers from a single unified location

Current features:
* All servers (logs, world, and associated configuration files) are stored in separate directories, by default located in *~/.minecraft-server*
* All backups are stored in separate dated directories, by default located in *~/.minecraft-server/backups*
* * "backups" are just full copies of an entire server. The dated directory may contain backups of multiple servers for that day
* The server message of the day (MotD) may be viewed and changed prior to launch
* Prompts for backing up the server are presented when the server is stopped

Planned features:
* Ability to create a new server from a blank template, and populate the world with data from a chosen directory

## Requirements
The script requires the following packages and libraries:
* python
* * sys, getopt, pyjavaproperties

You may need to install pyjavaproperties:

$ pip install pyjavaproperties

## Installation
Clone the repository with

$ git clone https://github.com/Rhotias/mcserver.git

Copy the *mcserver* and *mcserver-motd* files to your directory of choice. *~/.local/bin/* is a good one, if that's on your $PATH. Make the primary script executable with

$ chmod +x mcserver

Edit the *mcserver* file if necessary to ensure it points at an existing servers directory containing more directories where each consists of the components for one server

Each directory must contain a *run.sh* script that will cause that server to start. An example of a valid *run.sh* script is the following:

java -Xms2G -Xmx4G -jar ../minecraft_server.1.8.8.jar nogui

Note that the implication here is that the main servers directory contains server JAR files, which is recommended to keep them out of the backups. If you wish to keep the server JAR in the same directory as the server itself, do so and remove the *../* from the example above

## Execution
The primary program accepts no flags or arguments
212 changes: 212 additions & 0 deletions mcserver
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
#!/bin/sh

# Author: Rhotias B
# Create: 2015-07-10

# v0.1: 2015-07-10
# v1.0: 2015-07-14

serversDir=~/.minecraft-server
backupsDir=$serversDir/backups
itsNotTomorrowUntilIWakeUp=true # True - Up until 06:00, the date will be considered the previous day
reminder="Pause your torrents!" # An optional short reminder printed immediately after execution; set to "" to ignore

_requestServer() # _resultVar
{
local _requestServer_resultVar=$1
local serversArr=()

# Get array of directories in the serverDir, that aren't $backupsDir
for file in $serversDir/*; do
if [[ -d "$file" && "$(basename $file)" != "$(basename $backupsDir)" ]]; then
serversArr+=("$(basename $file)")
fi
done

# Request user input and set _resultVar to the chosen server
printf "%s\n" "Select a server by ID"
for index in ${!serversArr[*]}; do # Gets an array of the array indices
printf "%s\n" " ($index) ${serversArr[$index]}"
done
while true; do
read -p "[0]: " usrOpt
if [[ $usrOpt -ge 0 && $usrOpt -lt ${#serversArr[*]} ]]; then # Checks against total number of entries in array
# Set the variable which was passed to this function to the chosen server
eval $_requestServer_resultVar="${serversArr[$usrOpt]}"
break
else
printf "%s\n" " Error: Invalid selection"
fi
done
}

_launch()
{
# Put the server choice into a variable
local serverBasename
_requestServer serverBasename

# Offer the user to change the server MotD
_changeMotd serverBasename

printf "\n"

printf "Debug: pretending to start server in $serverBasename \n"
# cd "$serversDir/$serverBasename"; sh run.sh

printf "\n%s\n" "(Returning to mcserver)"

printf "%s\n" "Back up this server now?"
while true; do
read -p "[y]: " usrOpt
case $usrOpt in
y|Y|"")
_backUp "$serverBasename"; break
;;
n|N)
break
;;
*)
printf "%s\n" " Error: Invalid selection"
;;
esac
done
}

_backUp() # serverBasename
{
local serverBasename=$1

if [[ $serverBasename == "" ]]; then
_requestServer serverBasename
fi
serverDir="$serversDir/$serverBasename"

# Get current date in the local timezone
local date="$(date "+%Y-%m-%d")"

# Personal preference: I consider it to be the previous day if it's still not sunrise (06:00)
if [[ $itsNotTomorrowUntilIWakeUp == true && $(date "+%H") -lt 6 ]]; then
# Get current date in the UTC timezone, which is ~10 hours behind me here in Australia
local date="$(date -u "+%Y-%m-%d")"
fi

local bkDir="$backupsDir/$date"

# Create or use backup directory, or abort on error
printf "%s" "Making backup directory for $date... "
mkdir "$bkDir" >/dev/null 2>&1
if [[ $? == 0 ]]; then
printf "%s\n" "Done!"
elif [[ $? == 1 ]]; then
printf "%s\n" "Found existing directory; using it"
else
printf "%s\n" "Failed with error code $?. Aborting backup"
exit 1
fi

# Check for existing backups and either delete them or prepare to skip the copying step
local doCopy=true
if [[ -e "$bkDir/$serverBasename" ]]; then
printf "%s\n" "A backup of $serverBasename for $date already exists. Delete and replace it?"
while true; do
read -p "[y]: " usrOpt
case $usrOpt in
y|Y|"")
rm -rf "$bkDir/$serverBasename" >/dev/null 2>&1
break
;;
n|N)
doCopy=false
break
;;
*)
printf "%s\n" " Error: Invalid selection"
;;
esac
done
fi

# Copy the server data, or abort on error
if [[ $doCopy == true ]]; then
printf "%s" "Copying server files for $serverBasename... "
cp -r "$serverDir" "$bkDir" >/dev/null 2>&1
if [[ $? == 0 ]]; then
printf "%s\n" "Done!"
else
printf "%s\n" "Failed with error code $?. Aborting backup"
exit 1
fi
fi

# If necessary, recursively call the function to back up another server
printf "%s\n" "Back up another server for this same date?"
while true; do
read -p "[n]: " usrOpt
case $usrOpt in
n|N|"")
break
;;
y|Y)
local newServerBasename=$serverBasename
while [[ $newServerBasename == $serverBasename ]]; do
printf "%s\n" "Choose a server that isn't this one"
_requestServer newServerBasename
done
_backUp "$newServerBasename"
break
;;
*)
printf "%s\n" " Error: Invalid selection"
;;
esac
done
}

_changeMotd() # serverBasename
{
local infile="$serversDir/$serverBasename/server.properties"

if [[ -e $infile ]]; then
local motd="$(python mcserver-motd $infile -g)"

printf "%s\n" "Set message of the day"
while true; do
read -p "[$motd]: " usrOpt
case "$usrOpt" in
"")
break
;;
*)
python mcserver-motd $infile -s "$usrOpt"
break
;;
esac
done
else # infile does not exist
printf "%s\n" "mcserver error: $infile does not exist. It may not have been created yet"
fi
}

# program
if [[ $reminder != "" ]]; then
printf "%s\n" "(Reminder: $reminder)"
fi
printf "%s\n" "Select mode"
printf "%s\n" " (0) Launch"
printf "%s\n" " (1) Create backup"
while true; do
read -p "[0]: " usrOpt
case $usrOpt in
0|launch|l|"")
_launch; break
;;
1|create|backup|c|b)
_backUp; break
;;
*)
printf "%s\n" " Error: Invalid selection"
;;
esac
done
# end program
53 changes: 53 additions & 0 deletions mcserver-motd
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env python

# Author : Rhotias B
# Create : 2015-10-01

# This is a support script for the mcserver Bash script. If you want to though, you can make it executable with "chmod +x mcserver-motd" and use it as described in the usage

import sys, getopt
from pyjavaproperties import Properties

def showUsage():
print "Usage: mcserver-motd <infile.properties> -g"
print " or: mcserver-motd <infile.properties> -s <\"new message\">"
print "For the given file, get the current MotD or set a new one"

def main(infile, argv):
if len(argv) == 0:
showUsage()
sys.exit(2)

try:
opts, args = getopt.getopt(argv, "hgs:")
except getopt.GetoptError:
showUsage()
sys.exit(2)

try:
p = Properties()
p.load(open(infile))
except IOError as detail:
sys.exit( "{} {}".format("mcserver-motd error:", detail) )

for opt, arg in opts:
if opt == "-g":
print p["motd"]
elif opt == "-s":
p["motd"] = arg
elif opt == "-h":
showUsage()

p.store(open(infile,"w"))
# end def

# program
try:
infile = sys.argv[1]
except IndexError:
showUsage()
sys.exit(2)

if __name__ == "__main__":
main(infile, sys.argv[2:])
# end program
9 changes: 9 additions & 0 deletions mcserver.sublime-project
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"folders":
[
{
"path": ".",
"file_exclude_patterns": ["*.sublime-*"]
}
]
}

0 comments on commit 4b05101

Please sign in to comment.