Alle Tutorials
Auf dieser Seite
Schritt 3: FXServer-Artefakte automatisch aktualisieren
Ein Update-Script, das die aktuelle Version über die Cfx-Changelog-API holt, nur die Artefakt-Dateien tauscht und bei einem Fehlstart den alten Stand zurückholt. Dazu der passende Cron-Eintrag.
Das hier ist der dritte Teil der FiveM-Reihe. Nach den Schritten 1 und 2 läuft der Server und das Panel ist sicher erreichbar. Bleibt die Frage, wer die Artefakte aktuell hält.
FiveM-Artefakte veralten schnell. Alle paar Wochen verlangt der Client einen neueren Build, und dann steht dasselbe Ritual an: Buildnummer heraussuchen, Tarball herunterladen, Dienst stoppen, Dateien tauschen, Besitzer richten, Dienst starten. Das macht man dreimal gern und beim vierten Mal nachlässig.
Die fertigen Dateien
| Datei | Zweck |
|---|---|
update-fxserver.sh | der Updater, den dieses Tutorial erklärt |
install-fxserver.sh | interaktiver Installer, der Unit, Updater und Cron in einem Durchlauf einrichtet |
fivem.service | die systemd-Unit aus Schritt 1 als kommentierte Vorlage |
txadmin-vhost.conf | der Apache-vHost aus Schritt 2 |
Voraussetzungen
- ein laufender FXServer als systemd-Dienst, siehe Schritt 1
- die Trennung von Artefakt und Serverdaten in zwei Verzeichnisse
/opt/fivem/
├── server/ ← das Artefakt. run.sh + alpine/. Wird bei jedem Update ersetzt
└── server-data/ ← Deine resources/, server.cfg, cache/. Bleibt unangetastetapt update
apt install -y curl tar xz-utils jq cronjq ist nicht zwingend, das Script hat einen grep-Rückfallweg. Der braucht
aber grep -P, und das fehlt auf abgespeckten Systemen mit BusyBox. Wer jq
installiert, umgeht die Frage.
Schritt 3.1: Die Changelog-API verstehen
Der ganze Automatismus hängt an einer einzigen Adresse:
curl -fsSL https://changelogs-live.fivem.net/api/changelog/versions/linux/server | jqInteressant sind vier Felder:
| Feld | Inhalt |
|---|---|
recommended | Buildnummer des empfohlenen Builds |
recommended_download | direkte URL zum passenden fx.tar.xz |
latest | Buildnummer des neuesten Builds |
latest_download | direkte URL dazu |
Damit entfällt das Heraussuchen der Buildnummer von Hand. Das Script setzt den
gewünschten Kanal in eine Variable und liest das passende _download-Feld aus.
Schritt 3.2: Update-Script installieren
curl -fsSL https://uploads.musiker15.de/fivem/update-fxserver.sh \
-o /usr/local/bin/update-fxserver.sh
# Erst lesen, dann ausfuehrbar machen
less /usr/local/bin/update-fxserver.sh
chmod 0755 /usr/local/bin/update-fxserver.shAngepasst werden müssen nur die fünf Werte im Kopf:
FX_DIR="/opt/fivem/server" # Artefakt-Ordner (run.sh + alpine/)
FX_USER="fivem" # Besitzer der Dateien
FX_GROUP="fivem" # Gruppe
SERVICE="fivem" # Name der systemd-Unit ohne .service
CHANNEL="recommended" # "recommended" oder "latest"Wie es abläuft
- Version über die API ermitteln. Steht dieselbe Nummer schon in
.installed-version, endet der Lauf hier, ohne den Server anzufassen. - Artefakt nach
/tmpherunterladen und entpacken. Der Server läuft dabei weiter. - Dienst stoppen. Altes
alpine/undrun.shnach.previousverschieben. - Neues Artefakt einspielen,
chmod +x,chownauf den Dienstbenutzer. - Dienst starten und 15 Sekunden warten. Läuft er, wird
.previousgelöscht. Läuft er nicht, kommt der alte Stand zurück und wird gestartet.
Vier Entscheidungen darin, die den Unterschied machen
Erst herunterladen, dann stoppen. Download und Entpacken passieren
vollständig in /tmp, bevor der Dienst angefasst wird. Ist die API nicht
erreichbar oder das Archiv kaputt, bricht das Script ab und der Server läuft
einfach weiter. Ein Script, das zuerst stoppt und dann feststellt, dass es
keinen Download gibt, hinterlässt einen toten Server.
Verschieben statt löschen. Das alte alpine/ wandert nach .previous,
nicht in den Papierkorb. Geht der Tausch schief, oder startet der Dienst danach
nicht, holt die restore-Funktion den alten Stand zurück und fährt ihn hoch.
run.sh über find suchen, nicht raten. Die Archivstruktur hat sich in der
Vergangenheit geändert, mal mit Wrapper-Ordner, mal ohne. find -maxdepth 2
findet beides, und das Script bricht sauber ab, wenn es gar nichts findet.
chown -R nach jedem Tausch. Das Script läuft als root, cp -a erhält die
Besitzer aus dem Archiv. Ohne das chown gehören die neuen Dateien root, und
der Dienst startet als fivem nicht mehr.
Schritt 3.3: Cron-Eintrag
crontab -ePATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# managed-by: fxserver
0 5 * * 1 /usr/local/bin/update-fxserver.sh >> /var/log/fxserver-update.log 2>&1touch /var/log/fxserver-update.log
crontab -lDie PATH-Zeile ist nötig, weil cron mit einem sehr kurzen PATH startet.
systemctl liegt unter /usr/bin, jq je nach System woanders, und ein
Script, das im Terminal läuft und im Cron nicht, hat fast immer diese Ursache.
Ein Wochenrhythmus reicht in der Praxis. Täglich zu aktualisieren bringt bei
recommended nichts, weil sich der Wert ohnehin nur alle paar Wochen bewegt,
erhöht aber die Zahl der Neustarts.
Schritt 3.4: Testen, bevor der Cron das erste Mal läuft
Einmal von Hand aufrufen und zusehen:
sudo /usr/local/bin/update-fxserver.shUnd danach den Cron-Weg selbst prüfen, denn der läuft in einer anderen Umgebung:
sudo env -i /bin/bash --noprofile --norc -c \
'PATH=/usr/bin:/bin /usr/local/bin/update-fxserver.sh'env -i wirft die komplette Umgebung weg. Läuft das Script auch so durch, wird
es im Cron nicht an einer fehlenden Variablen scheitern.
# Was hat der Cron zuletzt getan
tail -n 40 /var/log/fxserver-update.log
# Welche Version liegt gerade
cat /opt/fivem/server/.installed-version
# Laeuft der Server, und seit wann
systemctl status fivemAlles auf einmal: der Installer
Wer bei null anfängt oder einen zweiten Server aufsetzt, tippt die Konfiguration sonst mehrfach ab. Der Installer fragt alles einmal ab und schreibt Unit, Update-Script und Cron-Eintrag daraus.
curl -fsSL https://uploads.musiker15.de/fivem/install-fxserver.sh -o install-fxserver.sh
less install-fxserver.sh # bitte wirklich lesen
bash -n install-fxserver.sh # Syntaxpruefung, fuehrt nichts aus
chmod +x install-fxserver.sh
sudo ./install-fxserver.shEr fragt der Reihe nach: Artefakt- und Datenverzeichnis, Benutzer und Gruppe, Name der Unit, Startmodus (txAdmin oder direkt), Zielpfad und Kanal des Updaters, Zeitplan des Crons. Geschrieben wird erst nach einer Zusammenfassung, die alles noch einmal zeigt, und die Bestätigung steht auf "Nein" als Vorgabe.
Drei Dinge, die ein selbstgebauter Installer leicht falsch macht und die dieser deshalb bewusst anders löst:
- Erst fragen, dann zusammenfassen, dann schreiben. Ein Installer, der nach jeder Frage sofort etwas anlegt, hinterlässt bei einem Abbruch in der Mitte einen halben Zustand.
- Beim Erzeugen des Update-Scripts zwei getrennte Heredocs. Der Kopf mit den
Werten wird expandiert (
<< CONF), der Logikteil darf es nicht sein (<< 'LOGIC'). Sonst ersetzt die Installationsshell jedes$FX_DIRund$0im erzeugten Script durch ihren eigenen, meist leeren Wert. Danach prüft der Installer das Ergebnis mitbash -n. - Beim Cron-Eintrag die eigenen alten Zeilen herausfiltern, und zwar
einschließlich der
PATH=-Zeile. Sonst sammelt sich bei jedem weiteren Lauf eine zusätzliche davon an.
Häufige Fehler
| Meldung oder Symptom | Ursache | Lösung |
|---|---|---|
/usr/bin/env^M: bad interpreter | Datei hat CRLF statt LF | sed -i 's/\r$//' update-fxserver.sh |
Download-URL konnte nicht ermittelt werden. | jq fehlt und grep -P wird nicht unterstützt | apt install jq |
| Script läuft im Terminal, im Cron nicht | cron startet mit minimalem PATH | PATH=-Zeile in die crontab, siehe Schritt 3.3 |
| Dienst startet nach dem Update nicht | Besitzer der neuen Dateien ist root | chown -R fivem:fivem prüfen |
| Port 30120 beim Start belegt | KillMode=process, Kindprozesse überleben | auf KillMode=mixed umstellen |
| Ressourcen nach dem Update verschwunden | FX_DIR zeigt auf das Datenverzeichnis | FX_DIR korrigieren, nur server/ eintragen |
| Server läuft in Inkompatibilitäten | Kanal steht auf latest | CHANNEL="recommended" setzen |
| Spieler fliegen mitten am Abend raus | Cron-Zeit liegt in der Hauptzeit | Zeitfenster verschieben |
| Update läuft, ändert aber nie etwas | Version ist bereits aktuell | kein Fehler, .installed-version prüfen |
Was das hier bewusst nicht tut
Es prüft keine Signatur. Der Download kommt über HTTPS von einer Cfx-Adresse, aber es gibt keine Prüfsumme, gegen die sich das Archiv verifizieren ließe. Wer das braucht, bleibt beim manuellen Weg und prüft die Artefakte selbst.
Es sichert server-data/ nicht. Das Script fasst das Verzeichnis nicht an,
aber ein Update ist trotzdem ein guter Zeitpunkt für ein Backup der Ressourcen
und der Datenbank. Das gehört in einen eigenen Cron, nicht in diesen.
Es rollt keine Datenbankmigrationen zurück. Der Rückweg stellt die Artefakt-Dateien wieder her, mehr nicht. Alles, was Ressourcen beim ersten Start in die Datenbank schreiben, bleibt.