Skip to content

Skripte Referenz

ElGregor edited this page Aug 15, 2026 · 1 revision

Skripte-Referenz — alle Automatisierungs-Skripte im Detail

Home · Zurück: Makefile-Referenz

Alle Betriebstätigkeiten dieses Repos laufen über Shell-Skripte in scripts/ (plus gcp/sync-backups.sh für die Failover-Spiegelung, siehe unten). Das Makefile ist nur ein dünner Wrapper: Die meisten Targets rufen genau ein Skript hier auf (1:1 aus dem Makefile, siehe Makefile-Referenz). Ausnahmen (1:1 aus dem Makefile): make mods ruft zwei Skripte (mods-validate.sh && mods-generate.sh), start/stop/restart/logs gehen direkt an systemctl/journalctl statt an ein Skript, und failover-sync ruft gcp/sync-backups.sh auf. Diese Seite dokumentiert Zweck, Aufruf, Ablauf, Abhängigkeiten und Exit-Verhalten — alles direkt aus dem Quellcode (Repo-Verhalten, 1:1).

Überblick

Linux-Skripte (12) + gemeinsame Bibliothek

Skript Zweck Aufruf
announce.sh In-Game-Neustartwarnung via RCON (Countdown 15/5/1 Min, Repo-Default) bash scripts/announce.sh
backup.sh tar.gz-Backup aus Saves + Server, Rotation, Discord bash scripts/backup.sh [label]
healthcheck.sh Prozess- + UDP-Port- + Log-Fehler-Prüfung bash scripts/healthcheck.sh
install.sh Erstinstallation SteamCMD + App 380870 (idempotent) bash scripts/install.sh
mods-generate.sh mods.yaml → workshop-items.txt (WorkshopItems/Mods/Map) bash scripts/mods-generate.sh
mods-validate.sh mods.yaml prüfen (Duplikate, Deps, TODO-Platzhalter) bash scripts/mods-validate.sh
monitor.sh Watchdog: Crash erkennen, Neustart, Notify bash scripts/monitor.sh (Cron)
notify.sh Manueller Discord-Ping bash scripts/notify.sh "Titel" "Text" [color]
render-config.sh Templates + .env → fertige Server-Configs (envsubst) bash scripts/render-config.sh
restore.sh Interaktives Backup-Restore mit Snapshot vorher bash scripts/restore.sh
spawns-generate.sh spawns.yaml → Lua-Spawn-Configs bash scripts/spawns-generate.sh
update.sh Sicherer Update-Zyklus mit Auto-Rollback bash scripts/update.sh [--dry-run]
lib/common.sh Gemeinsame Bibliothek (env, log, notify, guards) wird gesourcet, nie direkt

Windows-Skripte (4)

Skript Zweck Aufruf
windows/install.ps1 Windows-Installation nach C:\pzserver powershell -File scripts/windows/install.ps1
windows/backup.ps1 Zip-Backup, behält 7 Archive (Repo-Default) powershell -File scripts/windows/backup.ps1
windows/update.ps1 Update: Stop → Backup → SteamCMD → Start powershell -File scripts/windows/update.ps1
windows/monitor.ps1 Watchdog per Aufgabenplanung (minütlich) powershell -File scripts/windows/monitor.ps1

Die Linux-Skripte im Detail

announce.sh — In-Game-Neustartwarnung

Zweck: Warnt Spieler per RCON (servermsg) vor einem Neustart. Aufruf:

bash scripts/announce.sh

Keine Argumente; wird von update.sh automatisch vor dem Stop aufgerufen.

Ablauf (1:1):

  1. Ohne mcrcon → Warnung ins Log, Ende mit 0 (no-op)
  2. RCON_ENABLEDtrue → sofortiges Ende mit 0
  3. „Server-Neustart in 15 Minuten (Wartung)" → sleep 600
  4. „… in 5 Minuten - bitte einloggen sichern!" → sleep 240
  5. „… in 1 Minute!" → sleep 60

Gesamtlaufzeit rund 15 Minuten (sleeps 600/240/60, Repo-Default). RCON geht an 127.0.0.1:${RCON_PORT} mit ${RCON_PASSWORD}; Einzelfehler werden ignoriert (|| true).

Abhängigkeiten: mcrcon (optional), RCON_ENABLED=true, RCON_PORT, RCON_PASSWORD. Exit: immer 0 — der Eltern-Prozess bricht nie ab.

backup.sh — Sicherung mit Rotation

Zweck: Packt Saves + Server in ein tar.gz, rotiert alte tägliche Backups, meldet nach Discord.

Aufruf:

bash scripts/backup.sh              # Label "daily" (Default)
bash scripts/backup.sh weekly       # wöchentliches Archiv
bash scripts/backup.sh pre-update   # Rollback-Anker (von update.sh aufgerufen)

Labels: daily (Default, Timer), weekly, pre-update (aus update.sh), frei wählbar.

Ablauf (1:1): Ziel ${BACKUP_DIR}/${LABEL}-${YYYYmmdd-HHMMSS}.tar.gz; tar -czf … -C "${PZ_DATA_DIR}" Saves Server. Tar-Fehler → Discord „Backup FEHLGESCHLAGEN" + exit 1. Rotation: ls -1t daily-*.tar.gz | tail -n +$((RETENTION_DAILY + 1)) | xargs rm -f behält die RETENTION_DAILY neuesten; zusätzlich löscht find … -mtime +$((RETENTION_WEEKLY * 7)) daily-Archive älter als RETENTION_WEEKLY × 7 Tage. Discord-OK-Meldung nur bei Label daily.

Abhängigkeiten: tar, find, xargs. Exit: 0 Erfolg, 1 tar-Fehler. Details: Backup-und-Restore.

healthcheck.sh — Gesundheits-Check

Zweck: Drei-stufige Prüfung; der Exit-Code meldet das Ergebnis. Aufruf: bash scripts/healthcheck.sh bzw. make healthcheck.

Ablauf (1:1):

  1. Prozess: pgrep -f "ProjectZomboid" oder systemctl is-active zomboid — sonst FAIL
  2. UDP-Port: ss -ulnp zeigt :${GAME_PORT} — sonst nur WARN (Server evtl. noch am Starten)
  3. Log-Scan: journalctl -u zomboid --since "5 min ago" auf OutOfMemory|Exception in thread|FATAL — Treffer = FAIL

Exit: 0 = gesund, 1 = Prozess weg oder kritische Logzeilen. Der 5-Minuten- Zeitraum und die Muster sind Repo-Default. Abhängigkeiten: sudo journalctl, ss.

install.sh — Erstinstallation

Zweck: SteamCMD + PZ Dedicated Server (App 380870) installieren, Verzeichnisse und Erst-Konfiguration richten. Idempotent, mehrfach ausführbar (Skriptkopf).

Aufruf: sudo make install bzw. bash scripts/install.sh.

Ablauf (1:1): Guards (need_env, curl, tar) → fehlendes SteamCMD per curl|tar von steamcdn-a.akamaihd.net nach ${STEAMCMD_DIR} → Verzeichnisse ${PZ_SERVER_DIR}, ${PZ_DATA_DIR}, ${BACKUP_DIR} anlegen → SteamCMD +force_install_dir … +login anonymous +app_update 380870 validate +quitrender-config.sh + mods-generate.sh → Hinweise (systemd enable, Firewall ${GAME_PORT}/udp + 16262/udp) → Discord „Installation abgeschlossen".

Abhängigkeiten: curl, tar; anonymous-Login genügt (Community-Quelle: SteamCMD-Doku). Details: SteamCMD-Referenz.

mods-generate.sh — Modliste generieren

Zweck: Baut config/generated/workshop-items.txt mit WorkshopItems=, Mods=, Map= aus mods.yaml. Aufruf: make mods.

Ablauf (1:1): Nur enabled: true-Mods; Sortierung nach Kategorien library → framework → map → gameplay → qol (Load-Order, Repo-Default); WorkshopItems= = Workshop-IDs semikolongetrennt; Mods= = Mod-IDs mit führendem Backslash je Eintrag (B42-Pflicht, z. B. \damnlib;\NeatUI_Framework); Map= = map_name-Werte plus Muldraugh, KY immer zuletzt; Konsolenzusammenfassung der aktiven Mods.

Abhängigkeiten: python3 + python3-yaml (Fehlen → klarer Abbruch). Hintergrund: Mods-Referenz.

mods-validate.sh — Modliste prüfen

Zweck: Validiert mods.yaml vor dem Generieren; läuft auch in der CI. Aufruf: make validate.

Ablauf (1:1): Prüft doppelte workshop_id und mod_id (Fehler), workshop_id im Bereich 3600000000–3600000099 (TODO-Platzhalter → Warnung) und ob jede requires-Angabe einer aktivierten Mod entspricht (sonst Fehler). Exit: 1 bei Fehlern, 0 bei bloßen Warnungen. Der Platzhalter-Bereich ist Repo-Default. Abhängigkeiten: python3 + python3-yaml.

monitor.sh — Watchdog

Zweck: Erkennt ungeplante Abstürze und startet neu; geplante Stops werden über ein Lockfile erkannt.

Aufruf:

bash scripts/monitor.sh    # minütlich per Cron (Eintrag: systemd-Referenz)

Ablauf (1:1):

  1. systemctl is-active zomboid → aktiv: exit 0
  2. Lockfile ${REPO_ROOT}/.planned-stop vorhanden → exit 0 (geplanter Stop, z. B. Update/Wartung)
  3. Sonst: Warnung, sudo systemctl restart zomboid, sleep 45 (Repo-Default)
  4. healthcheck.sh → Erfolg: Discord „Server war abgestuerzt und wurde neu gestartet"; Misserfolg: „KRITISCH: Neustart fehlgeschlagen - manuell pruefen!"

Exit: in allen Pfaden 0 — der Healthcheck-Status fließt nur in die Discord-Meldung. Details: Monitoring-und-Alerts.

notify.sh — manueller Discord-Ping

Zweck: Freier Hand-Ping ans Webhook (Test, spontane Meldungen). Aufruf: bash scripts/notify.sh "Titel" "Text" [color] — Defaults: „PZ-Server", „Test", Farbe 3447003 (alle Repo-Default). Schreibt danach „Notify gesendet" ins Log; ohne DISCORD_WEBHOOK_URL no-op (siehe lib/common.sh).

render-config.sh — Konfiguration rendern

Zweck: Rendert config/templates/*.tmpl mit .env-Werten nach ${PZ_DATA_DIR}/Server/; kopiert Sandbox-Preset und Spawn-Dateien. Aufruf: make render.

Ablauf (1:1): Guards need_env + need_cmd envsubst; erlaubte Variablen (envsubst-Filter): SERVER_NAME, PUBLIC_NAME, DESCRIPTION, MAX_PLAYERS, ADMIN_PASSWORD, SERVER_PASSWORD, RCON_PASSWORD, RCON_PORT, RCON_ENABLED, RAM_XMX, GAME_PORT, DIRECT_PORT; jede .tmpl → gleichnamige Datei im Zielordner; coop-balanced.lua${SERVER_NAME}_SandboxVars.lua; Spawn-Dateien bevorzugt aus config/generated/spawns/ (falls vorhanden), sonst config/spawns/, Prefix servertest wird zu ${SERVER_NAME} umbenannt.

Abhängigkeiten: envsubst (Paket gettext-base — Heuristik für den Paketnamen; das Skript prüft nur das Kommando). Hintergrund: Server-Konfiguration.

restore.sh — interaktives Wiederherstellen

Zweck: Spielt ein Backup zurück und sichert vorher den aktuellen Stand.

Aufruf:

make restore    # interaktiv (Backup wählen, bestätigen)

Ablauf (1:1): Backups neueste zuerst nummeriert listen (keine → exit 1) → Auswahl prüfen (ungültig → exit 1) → Bestätigung [j/N] (Default: Abbruch mit exit 0) → sudo systemctl stop zomboid → Sicherheits-Backup backup.sh pre-restoretar -xzf nach ${PZ_DATA_DIR}sudo systemctl start zomboidsleep 45 + healthcheck.sh → bei Erfolg Discord „Restore erfolgreich".

Abhängigkeiten: sudo systemctl, tar. Details: Backup-und-Restore.

spawns-generate.sh — Spawn-Configs generieren

Zweck: Erzeugt aus spawns.yaml exakte Lua-Dateien unter config/generated/spawns/. Aufruf: make spawns.

Ablauf (1:1): Schreibt servertest_spawnregions.lua (Regionen als file- oder serverfile-Einträge) und je custom_spawns-Key eine servertest_<key>.lua mit SpawnPoints() je Beruf; Punkte als worldX, worldY, posX, posY, posZ (Default 0). Kopfzeile der generierten Dateien: „GENERIERT … NICHT manuell editieren" (Repo-Default).

Abhängigkeiten: python3 + python3-yaml. Hintergrund: Spawn-System.

update.sh — sicherer Update-Zyklus

Zweck: Kündigt an, stoppt, sichert, aktualisiert, startet, prüft — und rollt bei Fehlschlag automatisch zurück.

Aufruf:

make update                      # sofort, mit Announce + Airbag
bash scripts/update.sh --dry-run # nur anzeigen, nichts ausführen

Ablauf (1:1):

  1. Discord „Update-Zyklus gestartet (Server geht gleich offline)"
  2. announce.sh || true (Countdown, siehe oben)
  3. sudo systemctl stop zomboid
  4. backup.sh pre-update; neuestes pre-update-*.tar.gz = Rollback-Anker PRE_BACKUP
  5. SteamCMD +app_update 380870 validate +quit
  6. render-config.sh + mods-generate.sh
  7. sudo systemctl start zomboid; sleep 45 (Repo-Default)
  8. healthcheck.sh OK → Discord „Update erfolgreich", Ende
  9. Fehlschlag → Rollback: stop, tar -xzf ${PRE_BACKUP} -C ${PZ_DATA_DIR}, start, sleep 45, erneuter Healthcheck mit je einer Discord-Meldung; dann exit 1

Exit: 0 bei Erfolg (auch dry-run), 1 wenn der Healthcheck nach dem Update fehlschlägt — auch bei geglücktem Rollback (der Lauf gilt als gescheitert). Abhängigkeiten: sudo systemctl, SteamCMD plus die Abhängigkeiten der aufgerufenen Skripte (mcrcon, envsubst, python3). Details: Updates-und-Rollback.

lib/common.sh — die gemeinsame Bibliothek

Wird von jedem Skript zuerst gesourcet. Verhalten 1:1:

  • Strikt: set -euo pipefail (Repo-Default)
  • Pfade: REPO_ROOT = zwei Ebenen über scripts/lib/; .env dort; logs/ wird angelegt
  • env-Laden: .env wird — falls vorhanden — per set -a; source; set +a geladen und exportiert
  • Defaults bei fehlender/leerer .env (alle Repo-Default):
Variable Default
SERVER_NAME servertest
PZ_USER pzserver
PZ_SERVER_DIR /opt/pzserver/server
PZ_DATA_DIR /opt/pzserver/Zomboid
STEAMCMD_DIR /opt/pzserver/steamcmd
BACKUP_DIR /opt/pzserver/backups
RAM_XMX 12G
GAME_PORT 16261
DISCORD_WEBHOOK_URL leer (Notify aus)
RETENTION_DAILY 7
RETENTION_WEEKLY 4
  • Logging: log/warn/err mit Zeitstempel + Level nach stdout/stderr und angehängt an logs/server.log; die = err + exit 1
  • Guards: need_cmd <cmd> stirbt bei fehlendem Kommando; need_env stirbt ohne ${REPO_ROOT}/.env
  • notify: Discord-Embed (Titel, Text, Farbe, Hostname-Footer, UTC-Zeitstempel) per curl POST. Ohne DISCORD_WEBHOOK_URL sofortige Rückkehr (no-op); curl-Fehler werden nur verwarnt. Farb-Default 3447003; die Skripte nutzen 15105570 (orange), 3066993 (grün), 15158332 (rot) — alle Repo-Default.

Variablen im Überblick: ENV-Variablen.

GCP-Sync: gcp/sync-backups.sh

Liegt nicht in scripts/, sondern in gcp/ — gehört aber zur Skript-Familie, weil make failover-sync es direkt aufruft.

Zweck: Spiegelt den kompletten BACKUP_DIR in den GCP-Bucket, aus dem der Failover-Server im Notfall startet.

Aufruf:

make failover-sync              # = bash gcp/sync-backups.sh (Makefile, 1:1)
bash gcp/sync-backups.sh

Ablauf (1:1): Sourcet scripts/lib/common.sh, Guards need_cmd gsutil und need_env, dann gsutil -m rsync -r "$BACKUP_DIR" "gs://${GCP_BUCKET}" plus Log-Zeile. Laut gcp/README.md läuft der Sync täglich per Cron auf dem Hauptserver — 04:30 ist dort nur ein Vorschlag („z. B. 04:30, nach dem naechtlichen Backup"), keine feste Vorgabe.

Abhängigkeiten: gsutil (GCP-CLI-Werkzeug) und .env mit GCP_BUCKET sowie BACKUP_DIR. Exit: 1 bei fehlendem Kommando oder fehlender .env (via die), sonst 0. Details: GCP-Failover.

Windows-Skripte

Vier PowerShell-Skripte in scripts/windows/ bieten Parität zum Linux-Pfad für Admin-Maschine oder Win-Testserver (Skriptkopf install.ps1: „Haupt-Host ist Linux").

windows/install.ps1

Zweck: Windows-Pendant zu install.sh. Verhalten (1:1): Legt SteamCMD unter C:\steamcmd an (Download von steamcdn-a.akamaihd.net, falls steamcmd.exe fehlt), installiert den Server per +force_install_dir C:\pzserver +login anonymous +app_update 380870 validate +quit, Hinweis „Firewall: UDP 16261+16262 eingehend freigeben".

windows/backup.ps1

Zweck: Zip-Backup als Pendant zu backup.sh. Verhalten (1:1): Packt Saves + Server aus %USERPROFILE%\Zomboid als daily-<Ts>.zip nach C:\pzserver-backups; Sort-Object LastWriteTime -Descending | Select-Object -Skip 7 | Remove-Item behält die 7 neuesten Archive (Repo-Default, fest kodiert — keine .env-Konfiguration).

windows/update.ps1

Zweck: Update-Zyklus unter Windows. Verhalten (1:1): Stoppt ProjectZomboid*-Prozesse per Stop-Process -Force, legt pre-update-<Ts>.zip an, führt SteamCMD app_update 380870 validate aus, startet C:\pzserver\StartServer64.bat. Achtung (Repo-Verhalten): kein Announce, kein Healthcheck, kein Auto-Rollback — der Linux-Pfad ist der sicherere; Force-Stop kann ungespeicherten Spielstand riskieren (Heuristik — das Skript warnt nicht).

windows/monitor.ps1

Zweck: Watchdog-Pendant zu monitor.sh. Verhalten (1:1): Prüft Get-Process -Name "ProjectZomboid*"; fehlt der Prozess, startet es C:\pzserver\StartServer64.bat. Gedacht für die Aufgabenplanung (Task Scheduler), minütlich laut Skriptkopf — das Intervall stellt man in der Aufgabenplanung selbst ein (Heuristik). Kein .planned-stop-Pendant, keine Discord-Meldung (Repo-Verhalten). Setup: Setup-Windows.

Stolperfallen

  • Working Directory: Skripte am besten aus dem Repo-Root via make starten (Makefile ruft bash scripts/… relativ zum Repo-Root auf, Repo-Default). common.sh leitet REPO_ROOT zwar aus BASH_SOURCE ab, aber need_env prüft strikt auf ${REPO_ROOT}/.env.
  • Exec-Flags: Nach frischem Clone können Exec-Bits fehlen; der Aufruf über bash scripts/<name>.sh umgeht das — deshalb ruft das Makefile explizit bash auf (Repo-Default; bash-Umgehung selbst: Heuristik).
  • python3-Abhängigkeit: mods-generate, mods-validate und spawns-generate brauchen python3 plus python3-yaml; Fehlen bricht mit klarem Fehler ab (1:1: „FEHLER: python3-yaml fehlt").
  • sudo: update.sh, restore.sh und monitor.sh rufen sudo systemctl — im Cron-Kontext braucht der ausführende Nutzer passwortloses sudo für systemctl oder Root-Cron (Heuristik, aus dem Skriptverhalten abgeleitet).
  • Optionale vs. Pflicht-Werkzeuge: announce läuft ohne mcrcon als no-op weiter; render-config stirbt ohne envsubst direkt ab (need_cmd).
  • gsutil nur bei GCP-Sync nötig: Der Guard need_cmd gsutil existiert ausschließlich in gcp/sync-backups.sh — fehlt das Kommando, bricht nur make failover-sync ab; alle anderen Skripte und Targets brauchen kein gsutil (1:1 aus dem Quellcode).
  • Stummes Discord: Ohne DISCORD_WEBHOOK_URL sind alle notify-Aufrufe no-ops — Fehler sieht man dann nur in logs/server.log (1:1 aus common.sh).

Weiter: systemd-Referenz (wie die Skripte an Timer/Cron gebunden sind) · Backup-und-Restore · Zurück: Makefile-Referenz

Clone this wiki locally