Skip to content

Instantly share code, notes, and snippets.

@JamesTheAwesomeDude
Last active December 12, 2022 09:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JamesTheAwesomeDude/7a582af73448e330fc7bcfb5efef68d1 to your computer and use it in GitHub Desktop.
Save JamesTheAwesomeDude/7a582af73448e330fc7bcfb5efef68d1 to your computer and use it in GitHub Desktop.
systemd user-unit file for Minecraft server
# ~/.config/systemd/user/minecraft@.service
# Setup:
# loginctl enable-linger "${USER}"
# systemctl --user daemon-reload
# ln -sfv ../../jars/paper.jar /var/minecraft/servers/survival/server.jar
# systemctl --user enable --now minecraft@"$(systemd-escape /var/minecraft/servers/survival)".service
[Unit]
Description=Minecraft Server (%I)
After=network.target
[Service]
Type=simple
WorkingDirectory=%I
KillSignal=SIGINT
#ExecStart=sh start.sh
ExecStart=java -jar server.jar
SuccessExitStatus=INT SIGINT 130
# https://serverfault.com/a/800631/175102
Restart=always
RestartSec=90
StartLimitIntervalSec=400
StartLimitBurst=3
[Install]
WantedBy=default.target
#!/usr/bin/env python3
import urllib3, json, sys, logging, os, errno, hashlib
# you might need to run one of these first:
# apt install python3-urllib3
# python3 -m pip install urllib3
# python3 -m pip install --user urllib3
# dnf install python3-urllib3
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
http = urllib3.PoolManager(headers={'user-agent': '"https://gist.github.com/JamesTheAwesomeDude/7a582af73448e330fc7bcfb5efef68d1"/2022.03.15'})
def getjson(url, *, suppress_error=False, http=http):
r = http.request('GET', url)
data = json.load(r)
if not suppress_error:
if ('error' in data) and (data['error'] is not None):
raise RuntimeError(data['error'])
if r.status != 200:
raise urllib3.exceptions.HTTPError(r.status)
return data
if len(sys.argv) > 1:
version = sys.argv[-1]
else:
version = getjson("https://papermc.io/api/v2/projects/paper")['versions'][-1]
# this does NOT need to be refactored, I think; it's already sorted:
# https://github.com/PaperMC/bibliothek/blob/8b388693ee68df59852773f640c98f54e457b275/src/main/java/io/papermc/bibliothek/controller/v2/ProjectController.java#L107
logging.debug(f"version = {version}")
build = getjson(f"https://papermc.io/api/v2/projects/paper/versions/{version}")['builds'][-1]
#TODO: does this need to be refactored? It's unclear whether being-sorted is part of the promise:
# https://github.com/PaperMC/bibliothek/blob/8b388693ee68df59852773f640c98f54e457b275/src/main/java/io/papermc/bibliothek/controller/v2/VersionController.java#L112
logging.debug(f"build = {build}")
application = getjson(f"https://papermc.io/api/v2/projects/paper/versions/{version}/builds/{build}")['downloads']['application']
fname = application['name']
sha256sum_good = application['sha256']
logging.debug(f"sha256 = {sha256sum_good}")
if os.path.exists(fname) and '-f' not in sys.argv:
raise FileExistsError(errno.EEXIST, os.strerror(errno.EEXIST), fname)
logging.info(f"Downloading version {version}, build #{build} (to {fname})...")
with open(fname + '.part', 'wb') as f,\
http.request('GET', f"https://papermc.io/api/v2/projects/paper/versions/{version}/builds/{build}/downloads/{fname}", preload_content=False) as r:
hash = hashlib.sha256()
for chunk in r.stream():
f.write(chunk)
hash.update(chunk)
sha256sum = hash.hexdigest()
if sha256sum == sha256sum_good:
logging.info(f"SHA256 OK: {fname} [{sha256sum}]")
os.replace(fname + '.part', fname)
print("You should run:\n\tln -svf %s %s\n\tsystemctl --user restart \"minecraft@$(systemd-escape \"${PWD}\").service\"" % (repr(fname), repr('server.jar')))
else:
raise AssertionError(f"File is corrupted.\nexpected: {sha256sum_good}\ngot: {sha256sum}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment