Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Minecraft Server Backup and Upgrade Script
# Accompanying SystemD Unit file compatible with these locations/user:
# Expects the following minecraft directories:
# ./ The PWD is taken dynamically. In the SystemD unit, it is /var/lib/minecraft
# current The latest version. This will be the executable directory.
# 1.16.2 Directories will be created for every old version
# This script
# Install a root cronjob like:
# 02 00 * * * /var/lib/minecraft/ 2>> /var/lib/minecraft/update.log
use strict;
use warnings;
use LWP::UserAgent;
use LWP::Simple qw( getstore );
my $server_location = "$ENV{PWD}/current/";
my $temporary_new = "/tmp/";
my $user = 'minecraft';
my $group = 'minecraft';
# Take backup first
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
my $date = sprintf("%04d-%02d-%02d",$year+1900,$mon+1,$mday);
if (-e "${server_location}backups/$date.tar.gz") {
print STDERR "$date Already have a backup from today.\n";
} else {
`tar -cvpzf $date.tar.gz --exclude=${server_location}backups --exclude=${server_location}server.jar $server_location 2> /dev/null`;
`mv $ENV{PWD}/$date.tar.gz ${server_location}backups/`;
print STDERR "$date Backup made ${server_location}backups/$date.tar.gz\n";
my $current = `unzip -p ${server_location}server.jar version.json | grep 'name' | cut -d'"' -f4`;
chomp $current;
unless ($current) {
print STDERR "$date Current version not found.\n";
my $ua = LWP::UserAgent->new();
my $raw = $ua->get('')->{_content};
my $version;
if ($raw =~ m/version">minecraft_server\.([0-9\.]*)\.jar</) {
$version = $1;
} else {
print STDERR "$date No new version found\n";
if ($version eq $current) {
print STDERR "$date Already up to date.\n";
my $download;
if ($raw =~ m#.*(https://launcher\.mojang\.com/v1/objects/[a-f0-9]*/server\.jar).*#) {
$download = $1;
} else {
print STDERR "$date Couldn't find new JAR location.\n";
getstore( $download, $temporary_new."server.jar" );
my $shasum = `shasum ${temporary_new}server.jar | cut -d' ' -f1`;
chomp $shasum;
unless ($download eq "https://launcher\.mojang\.com/v1/objects/$shasum/server\.jar") {
print STDERR "$date shasum of download didn't match: $raw != https://launcher\.mojang\.com/v1/objects/$shasum/server\.jar\n";
unlink $temporary_new."server.jar";
# Untested
`systemctl stop minecraft`;
`mkdir ${server_location}../$current`;
`mv ${server_location}backups ${server_location}../$current/`;
`cp -r ${server_location}* ${server_location}../$current/`;
`mv ${temporary_new}server.jar ${server_location}`;
`mkdir ${server_location}backups`;
`chown -R $user:$group ${server_location}..`;
`systemctl start minecraft`;
print STDERR "$date Successfully updated!\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment