diff options
-rwxr-xr-x | builder.sh | 187 | ||||
-rwxr-xr-x | runner.sh | 109 |
2 files changed, 296 insertions, 0 deletions
diff --git a/builder.sh b/builder.sh new file mode 100755 index 0000000..5f647f8 --- /dev/null +++ b/builder.sh @@ -0,0 +1,187 @@ +#!/bin/bash + +# Minecraft Java serverdir builder + +function fail(){ + >&2 echo $@ + exit 1 +} + +# 1: file 2: attribute +function serverprop_get() { + sed -n "s/$2=\(.*\)$/\1/p" "$1" +} + +# 1: file 2: attribute 3: value +function serverprop_set() { + if grep -s "^$2=.*$" "$1"; then + sed -i "s/$2=.*$/$2=$3/g" "$1" + else + echo "$2=$3" >> "$1" + fi +} + +function confirm() { + [ -z "$NO_INTERACTIVE" ] || return 1 + + read -p "$@ [y/N] " choice + case $choice in + [yY]*) + return 0;; + *) + return 1 + esac +} + +# Sub Commands + +## world + +function world() { + local CMD="$1" + case $CMD in + list) ;& + create) ;& + clone) ;& + backup) ;& + delete) ;& + assign) + shift + eval 'world_$CMD "$@"' + ;; + *) + fail "world: Unknown argument $CMD" + esac + + exit $? +} + +function world_exists() { + [ -d "$WORLDS/$1" ] + return $? +} + +# 1: world 2: instance +function world_assign() { + local WORLD="$1" + local INSTANCE="$2" + + world_exists "$WORLD" \ + || ( confirm "World not found. Create?" \ + && world_create "$WORLD" \ + || fail "World $WORLD not found." ) + + [ -f "$WORLDS/$WORLD.lock" ] && fail "$WORLD is already used by another instance." + + echo "ASSIGNED_TO=\"$INSTANCE\"" > "$WORLDS/$WORLD.lock" + + ln -s "$WORLDS/$WORLD" "$INSTANCES/$INSTANCE" + serverprop_set "$INSTANCES/$INSTANCE/server.properties" level-name "$WORLD" +} + + +# 1: name +function world_create() { + world_exists "$1" && fail "World already exists" + mkdir "$WORLDS/$1" +} + +## instance + +function instance() { + local CMD="$1" + case $CMD in + list) ;& + create) ;& + delete) ;& + start) ;& + stop) ;& + status) + shift + eval 'instance_$CMD "$@"' + ;; + *) + fail "instance: Unknown argument $CMD" + esac + + exit $? +} + +function instance_exists() { + [ -d "$INSTANCES/$1" ] + return $? +} + +# 1: name 2: world 3: version +function instance_create() { + local NAME="$1" + local WORLD="$2" + local VERSION="$3" + + instance_exists "$NAME" && fail "$NAME already exists." + mkdir "$INSTANCES/$NAME" + + version_install "$NAME" "$VERSION" + confirm "Accept minecraft EULA?" && serverprop_set "$INSTANCES/$NAME/eula.txt" eula true + + world_assign "$WORLD" "$NAME" +} + +function instance_start() { + instance_exists "$1" || fail "instance $1 not found." + + + # TODO +} + +## version + +function version() { + fail "not implemented" +} + +function version_exists() { + [ -f "$VERSIONS/$1.jar" ] + return $? +} + +# 1: instance 2: version +function version_install() { + instance_exists "$1" || fail "instance $1 not found." + version_exists "$2" || fail "version $2 not found." + + local PWD=$(pwd) + cd "$INSTANCES/$1" + + [ -e "$2.jar" ] && rm "$2.jar" + + ln -s "$VERSIONS/$2.jar" "$2.jar" + + serverprop_set settings.sh MCJAR "$2.jar" + + cd "$PWD" +} + +# NO_INTERACTIVE=1 + +PREFIX=$(pwd) +VERSIONS="$PREFIX/versions" +WORLDS="$PREFIX/worlds" +INSTANCES="$PREFIX/instances" + +RUNNER="$PREFIX/runner.sh" + +[ -x ./settings.sh ] || fail "settings.sh not found." +source ./settings.sh + +CMD="$1" +case $CMD in + world) ;& + instance) ;& + version) + shift + eval '$CMD "$@"' + ;; + *) + fail "Unknown option $1" +esac diff --git a/runner.sh b/runner.sh new file mode 100755 index 0000000..1ec1fbc --- /dev/null +++ b/runner.sh @@ -0,0 +1,109 @@ +#!/bin/bash + +# Minecraft Java runner script + +function stop() { + running || exit 0 + test -p stdin || exit 1 + echo stop > stdin + + >&2 echo -n Waiting for server to stop + while kill -s 0 $PID > /dev/null 2>&1; do + sleep 1 + >&2 echo -n . + done + + >&2 echo Done! + + rm server.pid stdin + + exit 0 +} + +function start() { + running && fail "Server appears to already be running. PID: $PID" + + [ -z "$JVMARGS" ] && echo 'WARNING: $JVMARGS not set' + [ -e stdin -a ! -p stdin ] && rm stdin + + mkfifo stdin + + "$JAVA" $JVMARGS -jar "$MCJAR" -nogui $MCARGS \ + < <(while [ -p stdin ]; do timeout 10s cat stdin; done) \ + > /dev/null & + PID=$! + + echo $PID > server.pid + echo "Started server with PID $PID" + + exit 0 +} + +function attach() { + running || fail "Server is not running." + + echo "CTRL-D (EOF) to exit." + + tail -f logs/latest.log & + TAILPID=$! + + while read line; do + echo "$line" > stdin + done + + kill -s SIGKILL $TAILPID + + exit 0 +} + +function running() { + [ -e server.pid ] || return 1 + + PID=$(cat server.pid) + kill -s 0 $PID && return 0 + + rm server.pid stdin + return 1 +} > /dev/null 2>&1 + +function fail() { + >&2 echo $@ + exit 1 +} + +function stdin_redirector(){ + while [ -p stdin ]; do + cat stdin + done +} + +[ -e settings.sh ] && source settings.sh \ + || >&2 echo "WARNING: settings.sh not found." +# settings.sh +# JVMARGS, JAVA, MCARGS, MCJAR + +JAVA=${JAVA:-java} +MCJAR=${MCJAR:-server.jar} + +which "$JAVA" > /dev/null 2>&1 || fail "No java executable." + +case $1 in + start) + start;; + stop) + stop;; + status) + running || fail "Server is not running." + >&2 echo "Server is running" + exit 0;; + attach) + attach;; + command) + running || fail "Server is not running." + shift + echo $@ > stdin;; + *) + >&2 echo "Minecraft Java server runner" + >&2 echo "$0 start|stop|status|attach|command ..." + fail "Invalid argument $1" +esac |