Tutorials/Linux server update script

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
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
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
 * 1) !/bin/sh


 * 1) Wrapper for updatemcjar.sh
 * 1) 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
 * 1) !/bin/sh


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

set -e
 * 1) Error out script on errors

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

NORMAL_OUT=/dev/stdout ERROR_OUT=/dev/stderr
 * 1) Output paths

FLAG_FORCE= FLAG_VERSION= FLAG_CONFIRM= FLAG_TEST=
 * 1) Parameter Flags

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 }
 * 1) Help Page

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
 * 1) Check Script Parameters

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