Skip to content

Commit

Permalink
initial files
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanielc committed May 30, 2016
1 parent a4c35f6 commit 39ae41c
Show file tree
Hide file tree
Showing 5 changed files with 278 additions and 0 deletions.
20 changes: 20 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.DEFAULT = install

PREFIX ?= /

.PHONY: install
install:
install -D -m0644 src/[email protected] \
$(PREFIX)/usr/lib/systemd/system/[email protected]
install -D -m0644 src/[email protected] \
$(PREFIX)/usr/lib/systemd/system/[email protected]
install -D -m0644 src/[email protected] \
$(PREFIX)/usr/lib/systemd/system/[email protected]
install -D -m0755 src/minecraftctl.sh $(PREFIX)/usr/bin/minecraftctl

.PHONY: uninstall
uninstall:
rm $(PREFIX)/usr/lib/systemd/system/[email protected]
rm $(PREFIX)/usr/lib/systemd/system/[email protected]
rm $(PREFIX)/usr/lib/systemd/system/[email protected]
rm $(PREFIX)/usr/bin/minecraftctl
223 changes: 223 additions & 0 deletions src/minecraftctl
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
#!/bin/bash

# Launch Minecraft docker container

set -e

# Default listen port
# This is the published host port,
# internally the container always listens on 25565
PORT=${PORT-25565}

# Default max java heap size in MB
MAXHEAP=${MAXHEAP-2048}

# Default min java heap size in MB
MINHEAP=${MINHEAP-512}

# Path to docker executable
DOCKER=${DOCKER-$(which docker)}

# Wether to mount a persistent volume for the server
# If true a volume will not be mounted and a restart will lose all world data
EPHEMERAL=${EPHEMERAL-false}

# Directory for persisting minecraft data
DATA_DIR=${DATA_DIR-/srv/minecraft}
# Relative directory to $DATA_DIR for saving minecraft backups
BACKUP_DIR=${BACKUP_DIR-"./backups"}

# IDs of minecraft user and group
MINECRAFT_UID=${MINECRAFT_UID-$(id -u minecraft)}
MINECRAFT_GID=${MINECRAFT_GID-$(id -g minecraft)}

# Name of world dir
LEVEL=${LEVEL-world}

# Game command timeout
TIMEOUT=${TIMEOUT-0}

usage() {
echo "Usage: $0 [start|stop|restart|status|backup] <name>"
echo ""
echo "Name is a name for the container and the data dir"
exit 1
}

# Check if container is running
running() {
status="$($DOCKER inspect -f '{{.State.Status}}' "$name" 2>/dev/null)"
test running = "$status"
return $?
}

is_anyone_online() {
player_count=$(game_command list "players online:" | sed -r 's/.*([[:digit:]]+)\/[[:digit:]]+ players online:.*/\1/')
test $player_count -ne 0
return $?
}

# Start the minecraft docker container
start() {
if running
then
echo "Server already running..."
exit 0
fi
stop_container

vol_mount="--volume=$DATA_DIR/$name:/data"
if $EPHEMERAL
then
vol_mount=""
echo "Ephemeral server, a restart will lose all world data"
fi

$DOCKER run -d -i \
--name "$name" \
$vol_mount \
-p $PORT:25565 \
-e "JVM_OPTS=-Xmx${MAXHEAP}M -Xms${MINHEAP}M" \
-e EULA=true \
-e "VERSION=$VERSION" \
-e "DIFFICULTY=$DIFFICULTY" \
-e "WHITELIST=$WHITELIST" \
-e "OPS=$OPS" \
-e "ICON=$ICON" \
-e "MAX_PLAYERS=$MAX_PLAYERS" \
-e "MAX_WORLD_SIZE=$MAX_WORLD_SIZE" \
-e "ALLOW_NETHER=$ALLOW_NETHER" \
-e "ANNOUNCE_PLAYER_ACHIEVEMENTS=$ANNOUNCE_PLAYER_ACHIEVEMENTS" \
-e "ENABLE_COMMAND_BLOCK=$ENABLE_COMMAND_BLOCK" \
-e "FORCE_GAMEMODE=$FORCE_GAMEMODE" \
-e "GENERATE_STRUCTURES=$GENERATE_STRUCTURES" \
-e "HARDCORE=$HARDCORE" \
-e "MAX_BUILD_HEIGHT=$MAX_BUILD_HEIGHT" \
-e "MAX_TICK_TIME=$MAX_TICK_TIME" \
-e "SPAWN_MONSTERS=$SPAWN_MONSTERS" \
-e "SPAWN_NPCS=$SPAWN_NPCS" \
-e "VIEW_DISTANCE=$VIEW_DISTANCE" \
-e "SEED=$SEED" \
-e "MODE=$MODE" \
-e "MOTD=$MOTD" \
-e "PVP=$PVP" \
-e "LEVEL_TYPE=$LEVEL_TYPE" \
-e "GENERATOR_SETTINGS=$GENERATOR_SETTINGS" \
-e "LEVEL=$LEVEL" \
-e "WORLD=$WORLD" \
-e "UID=$MINECRAFT_UID" \
-e "GID=$MINECRAFT_GID" \
itzg/minecraft-server

echo "Started minecraft container $name"

}

# Send a command to the game server
game_command() {
expected=$2
if [ -n "$expected" ]
then
# Start tailing log from end before we issue the command
timeout "$TIMEOUT" grep -m 1 "$expected" <($DOCKER logs -f --tail=0 $name) &
fi
# Issue command
echo "$1" | $DOCKER attach "$name"
# Wait for grep if any
wait
}

# Do a world backup
backup() {
filename="$name-$(date +%Y_%m_%d_%H.%M.%S).tar.gz"

game_command "say Starting backup..."
# Make sure we always turn saves back on
set +e
ret=0
game_command "save-off"
ret=$(($ret + $?))
game_command "save-all flush" "Saved the world"
ret=$(($ret + $?))
sync
ret=$(($ret + $?))
$DOCKER exec -u minecraft "$name" mkdir -p "/data/$BACKUP_DIR"
ret=$(($ret + $?))
$DOCKER exec -u minecraft "$name" tar -C /data -czf "$BACKUP_DIR/$filename" --totals "$LEVEL" server.properties
ret=$(($ret + $?))
game_command "save-on"
ret=$(($ret + $?))

game_command "say Backup finished"
exit $ret
}

# Stop the server
stop() {
if running
then
if is_anyone_online
then
game_command "save-all"
for i in {10..1}
do
game_command "say Server shutting down in ${i}s..."
sleep 1
done
game_command "say Shutting down..."
fi
game_command "stop"
# Wait for container to stop on its own now
$DOCKER wait "$name"
fi

stop_container
}

# Stop the container
stop_container() {
$DOCKER stop "$name" > /dev/null 2>&1 || true
$DOCKER rm "$name" > /dev/null 2>&1 || true
}


name=$2
if [ -z "$name" ]
then
usage
fi

if [ -n "$DEBUG" ]
then
set -x
fi

case "$1" in
status)
if running
then
echo "Minecraft server $name is running"
exit 0
else
echo "Minecraft server $name is stopped"
exit 2
fi
;;
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
backup)
backup
;;
*)
usage
;;
esac

6 changes: 6 additions & 0 deletions src/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[Unit]
Description=Backup %I Minceraft server

[Service]
Type=oneshot
ExecStart=/usr/bin/minecraftctl backup %i
11 changes: 11 additions & 0 deletions src/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[Unit]
Description=Weekly backup of Minecraft server %i

[Timer]
OnCalendar=weekly
Persistent=true


[Install]
WantedBy=multi-user.target

18 changes: 18 additions & 0 deletions src/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[Unit]
Description=Minecraft Container %I
After=docker.service
Requires=docker.service

[Service]
TimeoutStartSec=0
Restart=always
EnvironmentFile=-/etc/minecraft/%i
ExecStartPre=/usr/bin/minecraftctl start %i
ExecStart=/usr/bin/docker logs -f %i

ExecStop=-/usr/bin/minecraftctl stop %i
ExecStopPost=-/usr/bin/minecraftctl stop %i

[Install]
WantedBy=multi-user.target

0 comments on commit 39ae41c

Please sign in to comment.