#!/bin/bash set -euo pipefail # ================================================== # Konfiguration # ================================================== BASE="/opt" CURRENT="/opt/iventoy" PERSIST="/srv/iventoy" ISO_DIR="${PERSIST}/iso" CONFIG_DIR="${PERSIST}/config" CONFIG_FILE="${CONFIG_DIR}/config.dat" SERVICE="iventoy" TMP="/tmp/iventoy-update" GITHUB_REPO="ventoy/PXE" MAX_CONFIG_BACKUPS=10 KEEP_VERSIONS=3 # ================================================== # Ausgabe # ================================================== echo "==========================================" echo " iVentoy Update" echo "==========================================" echo # ================================================== # Root Check # ================================================== if [ "$(id -u)" -ne 0 ]; then echo "ERROR: Dieses Script muss als root laufen." exit 1 fi # ================================================== # Abhängigkeiten # ================================================== apt-get update -qq apt-get install -y -qq curl tar iproute2 >/dev/null # ================================================== # Persistente Verzeichnisse # ================================================== mkdir -p "$ISO_DIR" mkdir -p "$CONFIG_DIR" # ================================================== # Aktuelle Version online ermitteln # ================================================== echo "Ermittle aktuelle iVentoy-Version..." LATEST_TAG=$( curl -fsSL \ -o /dev/null \ -w '%{url_effective}' \ "https://github.com/${GITHUB_REPO}/releases/latest" \ | awk -F/ '{print $NF}' ) VERSION="${LATEST_TAG#v}" if [ -z "$VERSION" ]; then echo "ERROR: Konnte aktuelle Version nicht ermitteln." exit 1 fi TARGET="${BASE}/iventoy-${VERSION}" echo "Neueste Version: $VERSION" # ================================================== # Bereits aktuell? # ================================================== if [ -L "$CURRENT" ]; then CURRENT_TARGET=$(readlink -f "$CURRENT" || true) if [ "$CURRENT_TARGET" = "$TARGET" ]; then echo echo "==========================================" echo " iVentoy ist bereits aktuell" echo "==========================================" echo echo "Aktive Version: $VERSION" echo "Installation: $CURRENT -> $TARGET" echo exit 0 fi fi # ================================================== # Bestehende Config erstmalig übernehmen # ================================================== if [ ! -f "$CONFIG_FILE" ]; then if [ -f "${CURRENT}/data/config.dat" ]; then echo echo "Übernehme bestehende iVentoy Config..." cp -a "${CURRENT}/data/config.dat" "$CONFIG_FILE" else echo echo "WARNUNG: Keine bestehende config.dat gefunden." fi fi # ================================================== # Config Backup # ================================================== if [ -f "$CONFIG_FILE" ]; then BACKUP="${CONFIG_FILE}.bak-$(date +%Y%m%d-%H%M%S)" echo echo "Sichere Config:" echo " $BACKUP" cp -a "$CONFIG_FILE" "$BACKUP" # ---------------------------------------------- # Backup Rotation # ---------------------------------------------- echo "Behalte maximal ${MAX_CONFIG_BACKUPS} Config-Backups..." find "$CONFIG_DIR" \ -maxdepth 1 \ -type f \ -name 'config.dat.bak-*' \ -printf '%T@ %p\n' \ | sort -nr \ | tail -n +"$((MAX_CONFIG_BACKUPS + 1))" \ | cut -d' ' -f2- \ | xargs -r rm -f fi # ================================================== # Download / Entpacken # ================================================== if [ -d "$TARGET" ]; then echo echo "Version $VERSION ist bereits vorhanden:" echo " $TARGET" else rm -rf "$TMP" mkdir -p "$TMP" ARCHIVE="iventoy-${VERSION}-linux-x86_64-free.tar.gz" URL="https://github.com/${GITHUB_REPO}/releases/download/v${VERSION}/${ARCHIVE}" echo echo "Lade herunter:" echo " $URL" curl -fL "$URL" -o "${TMP}/${ARCHIVE}" echo echo "Entpacke iVentoy..." tar -xzf "${TMP}/${ARCHIVE}" -C "$TMP" EXTRACTED="${TMP}/iventoy-${VERSION}" if [ ! -d "$EXTRACTED" ]; then echo "ERROR: Erwartetes Verzeichnis wurde nicht gefunden:" echo " $EXTRACTED" exit 1 fi mv "$EXTRACTED" "$TARGET" fi # ================================================== # ISO Symlink # ================================================== echo echo "Setze ISO-Symlink..." rm -rf "${TARGET}/iso" ln -s "$ISO_DIR" "${TARGET}/iso" # ================================================== # Config Symlink # ================================================== if [ -f "$CONFIG_FILE" ]; then echo "Setze Config-Symlink..." rm -f "${TARGET}/data/config.dat" ln -s \ "$CONFIG_FILE" \ "${TARGET}/data/config.dat" fi # ================================================== # iVentoy stoppen # ================================================== echo echo "Stoppe iVentoy..." systemctl stop "$SERVICE" 2>/dev/null || true sleep 2 # ================================================== # Alte direkte Installation migrieren # ================================================== # # Falls /opt/iventoy beim ersten Lauf noch ein # echtes Verzeichnis statt eines Symlinks ist. # if [ -e "$CURRENT" ] && [ ! -L "$CURRENT" ]; then OLD="${BASE}/iventoy-old-$(date +%Y%m%d-%H%M%S)" echo echo "Bestehende Installation wird verschoben:" echo " $CURRENT -> $OLD" mv "$CURRENT" "$OLD" fi # ================================================== # Current Symlink atomar umschalten # ================================================== echo echo "Aktiviere iVentoy $VERSION..." ln -sfn "$TARGET" "${CURRENT}.new" mv -Tf "${CURRENT}.new" "$CURRENT" # ================================================== # Service starten # ================================================== echo echo "Starte iVentoy..." systemctl start "$SERVICE" sleep 4 # ================================================== # Healthcheck # ================================================== echo echo "Führe Healthcheck aus..." FAILED=0 # Service if systemctl is-active --quiet "$SERVICE"; then echo "OK: iVentoy systemd service is active" else echo "ERROR: iVentoy systemd service is NOT active" FAILED=1 fi # TCP 26000 if ss -lntH | awk '{print $4}' | grep -Eq '[:.]26000$'; then echo "OK: TCP 26000 is listening" else echo "ERROR: TCP 26000 is NOT listening" FAILED=1 fi # TCP 16000 if ss -lntH | awk '{print $4}' | grep -Eq '[:.]16000$'; then echo "OK: TCP 16000 is listening" else echo "ERROR: TCP 16000 is NOT listening" FAILED=1 fi # UDP 69 if ss -lnuH | awk '{print $4}' | grep -Eq '[:.]69$'; then echo "OK: UDP 69 is listening" else echo "ERROR: UDP 69 is NOT listening" FAILED=1 fi # UDP 4011 if ss -lnuH | awk '{print $4}' | grep -Eq '[:.]4011$'; then echo "OK: UDP 4011 is listening" else echo "ERROR: UDP 4011 is NOT listening" FAILED=1 fi # UDP 67 if ss -lnuH | awk '{print $4}' | grep -Eq '[:.]67$'; then echo "OK: UDP 67 is listening" else echo "ERROR: UDP 67 is NOT listening" FAILED=1 fi # Web GUI if curl -fsS \ --max-time 5 \ http://127.0.0.1:26000/ \ >/dev/null 2>&1; then echo "OK: Web GUI responds" else echo "ERROR: Web GUI does NOT respond" FAILED=1 fi # PXE HTTP Bind-IP bestimmen PXE_BIND=$(ss -lntH | awk '$4 ~ /:16000$/ {print $4; exit}') if [ -n "$PXE_BIND" ]; then PXE_IP="${PXE_BIND%:16000}" PXE_IP="${PXE_IP#[}" PXE_IP="${PXE_IP%]}" if [[ "$PXE_IP" == "*" || \ "$PXE_IP" == "0.0.0.0" || \ "$PXE_IP" == "::" ]]; then PXE_IP="127.0.0.1" fi if curl -sS \ --max-time 5 \ -o /dev/null \ "http://${PXE_IP}:16000/" \ >/dev/null 2>&1; then echo "OK: PXE HTTP service on ${PXE_IP}:16000 responds" else echo "ERROR: PXE HTTP service on ${PXE_IP}:16000 does NOT respond" FAILED=1 fi else echo "ERROR: Could not determine PXE HTTP bind address" FAILED=1 fi # ================================================== # Healthcheck fehlgeschlagen # ================================================== if [ "$FAILED" -ne 0 ]; then echo echo "==========================================" echo " UPDATE FEHLGESCHLAGEN" echo "==========================================" echo if [ -f "${CURRENT}/log/log.txt" ]; then echo "Letzte iVentoy Log-Einträge:" echo tail -n 50 "${CURRENT}/log/log.txt" || true fi echo echo "Alte iVentoy-Versionen wurden NICHT gelöscht." echo "Damit ist ein manueller Rollback weiterhin möglich." exit 1 fi # ================================================== # Alte Versionen aufräumen # ================================================== echo echo "Räume alte iVentoy-Versionen auf..." echo "Behalte maximal ${KEEP_VERSIONS} Versionen." ACTIVE_TARGET=$(readlink -f "$CURRENT") mapfile -t VERSION_DIRS < <( find "$BASE" \ -maxdepth 1 \ -mindepth 1 \ -type d \ -name 'iventoy-[0-9]*' \ -printf '%T@ %p\n' \ | sort -nr \ | cut -d' ' -f2- ) COUNT=0 for DIR in "${VERSION_DIRS[@]}"; do # Aktive Version niemals löschen if [ "$(readlink -f "$DIR")" = "$ACTIVE_TARGET" ]; then COUNT=$((COUNT + 1)) continue fi COUNT=$((COUNT + 1)) if [ "$COUNT" -gt "$KEEP_VERSIONS" ]; then echo "Lösche alte Version:" echo " $DIR" rm -rf "$DIR" fi done # ================================================== # Temp-Dateien aufräumen # ================================================== rm -rf "$TMP" # ================================================== # Abschluss # ================================================== echo echo "==========================================" echo " Update erfolgreich" echo "==========================================" echo echo "Aktive Version:" echo " $VERSION" echo echo "Installation:" echo " $CURRENT -> $TARGET" echo echo "Config:" echo " ${CURRENT}/data/config.dat -> $CONFIG_FILE" echo echo "ISO:" echo " ${CURRENT}/iso -> $ISO_DIR" echo echo "Config-Backups:" echo " maximal $MAX_CONFIG_BACKUPS" echo echo "Installierte iVentoy-Versionen:" echo " maximal $KEEP_VERSIONS" echo