Tutorials/Linux server update script

From Minecraft Wiki
Jump to: navigation, search
Warning
Since this is a wiki and anyone may modify any page at any time, it is suggested that you do not actually use this script but instead simply use it as a guideline for writing your own.


Information icon.svg
This feature is exclusive to Java Edition.

This is a detailed bash script to update a vanilla Minecraft server. Default parameters can be modified within the script, or passed in as parameters. Target installation version will default to the latest release, though any version can be specified.

This script was written on CentOS 7 but should work for any POSIX compliant Linux distribution so long as the dependencies are available.

Dependencies[edit]

This script relies on cURL to handle downloading of Mojang manifests and the server JAR file itself. The JSON parser jq is used to extract the relevant information out of the manifests.

On CentOS 7 jq is available through the EPEL repository. On other distributions it may be available, or may require installation from source.

To Install the required dependencies on CentOS 7 perform the following commands

yum update
yum -y install epel-release
yum -y install curl jq

Usage[edit]

This script only handles updating the server JAR file itself. Should you need to stop the server, change permissions on the newly downloaded file, and start the server again afterwards, a wrapper script is recommended. The following is a simple example wrapper script for a setup using a separate user and group for the server, and a server that is started and stopped through systemd.

Please be cautious. While these scripts worked when originally posted, anyone can edit the wiki, and furthermore your system or setup may be different than was used to create them.

updatemc.sh

#!/bin/sh

#------------
# Wrapper for updatemcjar.sh
#------------

JAR_PATH="/home/minecraft/server/server.jar"
echo "Stopping Minecraft"
systemctl stop minecraft
echo "Minecraft Stopped"
./updatemcjar.sh -y
chown minecraft:minecraft $JAR_PATH
chmod 750 $JAR_PATH
chmod +x $JAR_PATH
echo "Starting Minecraft"
systemctl start minecraft
echo "Minecraft Started"

The main script itself does all the heavy lifting, and has many configurable parameters based upon your setup.

updatemcjar.sh

#!/bin/sh

#----------------------------------------
# A shell script for updating the minecraft server jar file on Linux Servers
# Written by: Andrew Haskell
# Updated by: Zukaro Travon
# Last updated on: 2019.Sep.23
# Distributed under The MIT License (MIT)
#
# Dependencies
# 	cURL	For downloading of the manifest and jar files
#	jq	For parsing the manifests
#
#
#			---- IMPORTANT ----
# 	This script merely updates the minecraft server jar.
# 	Wrap this script in a wrapper script to take care of stopping and
#	starting your server based on your setup.
# 	If you need to change permissions on the final server jar do it from
#	within that warpper script as well.
#
# Example Wrapper Script:
# 	systemctl stop minecraft
#	./updatemcjar.sh -y --jar-path "/srv/minecraft/server.jar"
#	sudo chown minecraft:minecraft "/srv/minecraft/server.jar"
#	sudo chmod 750 "/srv/minecraft/server.jar"
#	sudo chmod +x "/srv/minecraft/server.jar"
#	systemctl start minecraft
#----------------------------------------

# Error out script on errors
set -e

# Default Settings (Can be changed through parameters)
TEMP_DIR='/tmp/updatemc/'
JAR_PATH='/home/minecraft/server/server.jar'
VERSION_MANIFEST='https://launchermeta.mojang.com/mc/game/version_manifest.json'

# Output paths
NORMAL_OUT=/dev/stdout
ERROR_OUT=/dev/stderr

# Parameter Flags
FLAG_FORCE=
FLAG_VERSION=
FLAG_CONFIRM=
FLAG_TEST=

# Help Page
usage()
{
	echo
	echo "----------------------------------------"
	echo "$0 - A tool for updating the minecraft server jar easily"
	echo "Written by: Andrew Haskell - Distributed under The MIT License (MIT)"
	echo
	echo "Dependencies:"
	echo "    cURL                 Included in most major distributions package repositories"
	echo "    jq                   Check your distribution repositories or build from source"
	echo
	echo "Usage: $0 [options]"
	echo
	echo "    -f, --force          If the Target Version SHA1 matches the current file's SHA1, force the update anyway, implies --yes"
	echo "    -y, --yes            Skip update confirmation"
	echo "    -v, --version        Specify a different target version. Without this parameter, the latest release version is used"
	echo "    -t, --test           Test the Target Version SHA1 against the current file's SHA1 without changing any files"
	echo "    -s, --silent         Suppress script output, implies --yes"
	echo "    --no-err             Suppress error messages (Dangerous!)"
	echo "    --temp-dir           Specify a different temporary directory, default is $TEMP_DIR"
	echo "    --jar-path           Specify a different final JAR path, default is $JAR_PATH"
	echo "    --manifest           Specify a different version manifest URL, default is $VERSION_MANIFEST"
	echo "    -h, --help           Print this help message"
	echo
	echo "Examle Usage:"
	echo "    $0                   Run the script normally"
	echo "    $0 -f                Force update the existing JAR"
	echo "    $0 -v 1.8.1 -y       Update to 1.8.1 without asking for confirmation"
	echo
	echo "----------------------------------------"
	echo 
}


# Check Script Parameters
while [ "$1" != "" ]; do
	case $1 in
		-f | --force )		FLAG_FORCE=1
					FLAG_CONFIRM=1
					;;
		-v | --version )	shift
					FLAG_VERSION=$1
					;;
		-y | --yes )		FLAG_CONFIRM=1
					;;
		-s | --silent )		NORMAL_OUT=/dev/null
					FLAG_CONFIRM=1
					;;
		--no-err )		ERROR_OUT=/dev/null
					;;
		--temp-dir )		shift
					TEMP_DIR=$1
					;;
		--jar-path )		shift
					JAR_PATH=$1
					;;
		--manifest )		shift
					VERSION_MANIFEST=$1
					;;
		-t | --test )		FLAG_TEST=1
					;;
		-h | --help )		usage
					exit
					;;
		* )			echo "Bad option specified"
					usage
					exit 1
					;;
	esac
	shift
done

echo "Clearing temp directory: $TEMP_DIR" > $NORMAL_OUT
mkdir -p $TEMP_DIR
DOWNLOADED_JAR="${TEMP_DIR}server.jar"
if [ -e $DOWNLOADED_JAR ]
then
	rm -f $DOWNLOADED_JAR
fi

echo "Downloading Version Manifest from: $VERSION_MANIFEST" > $NORMAL_OUT
VERSION_MANIFEST_DATA=$(curl -s "$VERSION_MANIFEST")
echo "Done" > $NORMAL_OUT

echo "Parsing Version Manifest" > $NORMAL_OUT
VERSION_LATEST=$(jq -rn --argjson version "$VERSION_MANIFEST_DATA" '$version.latest.release')
VERSION_TARGET=$VERSION_LATEST
echo "Latest released version: $VERSION_LATEST" > $NORMAL_OUT
if [ -n "$FLAG_VERSION" ]
then
	VERSION_TARGET=$FLAG_VERSION
	echo "Target version to download: $VERSION_TARGET" > $NORMAL_OUT
fi
PACKAGE_MANIFEST=$(echo "$VERSION_MANIFEST_DATA" | jq -r --arg VERSION_TARGET "$VERSION_TARGET" '.versions | .[] | select(.id==$VERSION_TARGET) | .url')
echo "Done" > $NORMAL_OUT

if [ -z "$PACKAGE_MANIFEST" ]
then
	echo "Could not find target version: $VERSION_TARGET within the manifest file. Was the target version incorrectly specified? If not then double check the Mojang version manifest by hand" > $ERROR_OUT
	exit 1
fi

echo "Downloading Package Manifest from: $PACKAGE_MANIFEST" > $NORMAL_OUT
PACKAGE_MANIFEST_DATA=$(curl -s "$PACKAGE_MANIFEST")
echo "Done" > $NORMAL_OUT

echo "Parsing Package Manifest" > $NORMAL_OUT
SERVER_NEWJAR_URL=$(jq -rn --argjson url "$PACKAGE_MANIFEST_DATA" '$url.downloads.server.url')
SERVER_NEWJAR_SHA1=$(jq -rn --argjson sha1 "$PACKAGE_MANIFEST_DATA" '$sha1.downloads.server.sha1')
echo "Done" > $NORMAL_OUT

echo "Calculating SHA1 of $JAR_PATH" > $NORMAL_OUT
SERVER_OLDJAR_SHA1=$(sha1sum "$JAR_PATH" | cut -d " " -f 1)

echo "Old JAR SHA1: $SERVER_OLDJAR_SHA1" > $NORMAL_OUT
echo "New JAR SHA1: $SERVER_NEWJAR_SHA1" > $NORMAL_OUT

if [ "$SERVER_OLDJAR_SHA1" = "$SERVER_NEWJAR_SHA1" ]
then
	echo "SHA1 sums match. $JAR_PATH is already target version" > $NORMAL_OUT
	if [ -z "$FLAG_TEST" ]
	then
		if [ -z "$FLAG_FORCE" ]
		then
			echo "Exiting" > $NORMAL_OUT
			exit
		else
			echo "Forcing JAR Update" > $NORMAL_OUT
		fi
	else
		exit
	fi
else
	echo "SHA1 sums mis-matched. $JAR_PATH differs from target version." > $NORMAL_OUT
	if [ -z "$FLAG_TEST" ]
	then
		if [ -z "$FLAG_CONFIRM" ]
		then
			while true; do
				read -p "Replace $JAR_PATH with latest? [y/n]: " yn
				case $yn in
					[Yy]* ) 	break
						;;
					[Nn]* ) 	echo "Exiting"
							exit
							;;
					* ) 		echo "Please answer Y(es) or N(o)"
							;;
				esac
			done
		fi
	else
		exit
	fi
fi

echo "Downloading new server JAR from: $SERVER_NEWJAR_URL to $DOWNLOADED_JAR" > $NORMAL_OUT
curl -s -L -f -o $DOWNLOADED_JAR $SERVER_NEWJAR_URL
echo "Done" > $NORMAL_OUT

echo "Calculating SHA1 of $DOWNLOADED_JAR" > $NORMAL_OUT
DOWNLOADED_SHA1=$(sha1sum $DOWNLOADED_JAR | cut -d " " -f 1)
echo "Dwn JAR SHA1: $DOWNLOADED_SHA1" > $NORMAL_OUT
echo "New JAR SHA1: $DOWNLOADED_SHA1" > $NORMAL_OUT


if [ "$DOWNLOADED_SHA1" = "$SERVER_NEWJAR_SHA1" ]
then
	echo "SHA1 sums match, proceeding" > $NORMAL_OUT
else
	echo "SHA1 sums mis-matched, check downloaded JAR at: $DOWNLOADED_JAR" > $ERROR_OUT
	exit 1
fi

JAR_PATH_BACKUP=${JAR_PATH}.bak
echo "Renaming $JAR_PATH to $JAR_PATH_BACKUP" > $NORMAL_OUT
mv $JAR_PATH $JAR_PATH_BACKUP

echo "Copying $DOWNLOADED_JAR to $JAR_PATH" > $NORMAL_OUT
cp $DOWNLOADED_JAR $JAR_PATH

echo "Re-Verifying $JAR_PATH" > $NORMAL_OUT
FINAL_SHA1=$(sha1sum $JAR_PATH | cut -d " " -f 1)
if [ "$FINAL_SHA1" = "$SERVER_NEWJAR_SHA1" ]
then
	echo "$JAR_PATH updated successfully to version: $VERSION_TARGET" > $NORMAL_OUT
	exit
else
	echo "SHA1 sums mis-matched, current JAR at: $JAR_PATH does NOT match the version attempting to be installed. Rolling Back" > $ERROR_OUT
	echo "Deleting $JAR_PATH" > $ERROR_OUT
	rm -f $JAR_PATH
	echo "Copying backup JAR from: $JAR_PATH_BACKUP to $JAR_PATH" > $ERROR_OUT
	cp $JAR_PATH_BACKUP $JAR_PATH
	echo "Original JAR file restored. Please check the files in $TEMP_DIR" > $ERROR_OUT
	exit
fi