#!/bin/bash # ESPO-23-Demo-zuruecksetzen - setzt eine Demo-Instanz auf den mit ESPO-22 gesicherten Grundstand zurueck. # Aufruf: ohne Argumente, taeglich um 02:00 ueber den Zeitplan des RMM. # Zwei unabhaengige Riegel gegen einen Lauf auf einer Kundeninstanz: Der Task ist nur auf der Demo eingeplant, # und dieses Skript laeuft nur auf Hostnamen espo-demo* - ein Fehlgriff wuerde sonst Kundendaten loeschen # (bewusste Abweichung von ADR 0012, siehe ADR 0014). set -u # Standzeile: zeigt im Protokoll, welche Fassung tatsaechlich gelaufen ist. echo "ESPO-23-Demo-zuruecksetzen, Skriptstand 2026-10-01" BASIS=/srv/espo GRUNDSTAND=/srv/espo-baseline COMPOSE=$BASIS/docker-compose.yml VG=ubuntu-vg SNAPSHOT=srv-vor-update WARTE_MAX=600 # Dieselbe Auswahl wie in ESPO-22: secrets/, Compose, bin/, data/config-override.php und data/logs/ bleiben, # wie sie sind. VERZEICHNISSE="mariadb data custom client-custom" fehler() { echo "FEHLER: $*"; echo "ESPO23_ERGEBNIS: FEHLER"; exit 1; } # Wartet, bis alle vier Container "healthy" melden - "starting" ist keine Aussage. alle_gesund() { local c for c in espocrm-db espocrm espocrm-daemon espocrm-websocket; do [ "$(docker inspect -f '{{.State.Health.Status}}' "$c" 2>/dev/null)" = "healthy" ] || return 1 done return 0 } # Nennt die Container, die noch nicht gesund sind - fuer die Fehlermeldung. nicht_gesund() { local c z="" for c in espocrm-db espocrm espocrm-daemon espocrm-websocket; do [ "$(docker inspect -f '{{.State.Health.Status}}' "$c" 2>/dev/null)" = "healthy" ] \ || z="$z $c=$(docker inspect -f '{{.State.Health.Status}}' "$c" 2>/dev/null || echo fehlt)" done printf '%s' "${z# }" } # Dieselben Merkmale wie in ESPO-22 - alle aus Dateien lesbar, also auch dann, wenn die Demo gerade klemmt. espo_version() { sed -n "s/^[[:space:]]*'version' => '\([^']*\)'.*/\1/p" "$1/data/state.php" 2>/dev/null | head -n 1; } db_image() { sed -n 's/^[[:space:]]*image:[[:space:]]*\(mariadb:[^[:space:]]*\).*/\1/p' "$COMPOSE" 2>/dev/null | head -n 1; } extension_ids() { ls -1 "$1/data/.backup/extensions" 2>/dev/null | sort | paste -sd ' '; } gesichert() { sed -n "s/^$1=//p" "$GRUNDSTAND/manifest" 2>/dev/null | head -n 1; } # 1. Vorbedingungen. Die Instanz muss dafuer nicht gesund sein - eine klemmende Demo soll der Reset ja reparieren. [ "$(id -u)" -eq 0 ] || fehler "nicht als root gestartet" [[ "$(hostname -s)" == espo-demo* ]] || fehler "nur auf Demo-Instanzen (Hostname espo-demo*), hier: $(hostname -s)" command -v docker >/dev/null && docker info >/dev/null 2>&1 || fehler "Docker laeuft nicht" command -v rsync >/dev/null || fehler "rsync fehlt - ESPO-22 installiert es beim Sichern" [ -f "$COMPOSE" ] || fehler "$COMPOSE fehlt - ist die Instanz deployt?" [ -s "$GRUNDSTAND/manifest" ] || fehler "kein Grundstand unter $GRUNDSTAND - zuerst ESPO-22 ausfuehren" for V in $VERZEICHNISSE; do [ -d "$GRUNDSTAND/$V" ] || fehler "Grundstand unvollstaendig: $V fehlt - ESPO-22 erneut ausfuehren" done if lvs --noheadings -o lv_name "$VG" 2>/dev/null | grep -qw "$SNAPSHOT"; then fehler "Snapshot '$SNAPSHOT' besteht - eine Aenderung ist noch nicht mit ESPO-11 bestaetigt" fi # 2. Passt der Grundstand noch? ESPO-10 aendert Version oder Image, ESPO-30 die Extensions. Ein Zuruecksetzen # wuerde das still rueckgaengig machen - dann lieber abbrechen und neu sichern lassen. IST="$(espo_version "$BASIS")"; SOLL="$(gesichert espo_version)" [ "$IST" = "$SOLL" ] || fehler "EspoCRM ist ${IST:-unbekannt}, der Grundstand ${SOLL:-unbekannt} - nach dem Update erst ESPO-22 ausfuehren" IST="$(db_image)"; SOLL="$(gesichert db_image)" [ "$IST" = "$SOLL" ] || fehler "MariaDB laut Compose ${IST:-unbekannt}, im Grundstand ${SOLL:-unbekannt} - erst ESPO-22 ausfuehren" [ "$(extension_ids "$BASIS")" = "$(gesichert extension_ids)" ] \ || fehler "die Extensions haben sich seit dem Grundstand geaendert (ESPO-30?) - erst ESPO-22 ausfuehren" # 3. Stoppen, zurueckkopieren, starten. Was auch passiert: Am Ende laeuft die Demo wieder. GESTOPPT=0 trap '[ "$GESTOPPT" -eq 1 ] && docker compose -f "$COMPOSE" up -d >/dev/null 2>&1' EXIT docker compose -f "$COMPOSE" stop >/dev/null 2>&1 || fehler "Stack nicht stoppbar" GESTOPPT=1 for V in $VERZEICHNISSE; do AUSNAHMEN=() [ "$V" = "data" ] && AUSNAHMEN=(--exclude=/logs/ --exclude=/config-override.php) rsync -a --numeric-ids --delete "${AUSNAHMEN[@]}" "$GRUNDSTAND/$V/" "$BASIS/$V/" || fehler "Zurueckkopieren von $V fehlgeschlagen" done START="$(docker compose -f "$COMPOSE" up -d 2>&1)" || { printf '%s\n' "$START" | tail -n 10; fehler "Start fehlgeschlagen"; } GESTOPPT=0 ENDE=$(( SECONDS + WARTE_MAX )) while [ "$SECONDS" -lt "$ENDE" ]; do alle_gesund && break sleep 10 done alle_gesund || fehler "nach ${WARTE_MAX}s nicht alle Container gesund: $(nicht_gesund)" # 4. Bericht. echo "--- Zurueckgesetzt auf den Grundstand" echo "gesichert: $(gesichert created)" echo "EspoCRM: $(gesichert espo_version)" echo "Extensions: $(gesichert extensions)" echo "--- Container" docker compose -f "$COMPOSE" ps --format 'table {{.Name}}\t{{.Status}}' 2>/dev/null echo "ESPO23_ERGEBNIS: OK"