|
|
|
@@ -52,6 +52,7 @@ WITH_DATA=1
|
|
|
|
|
STOP_OLD=1
|
|
|
|
|
ADOPT_KEY=1
|
|
|
|
|
TAG="latest"
|
|
|
|
|
ROLLBACK=""
|
|
|
|
|
#: Namenszusatz, unter dem ``rename.sh`` eine verdraengte Installation der
|
|
|
|
|
#: Fassung 1.x ablegt. Beide Skripte muessen denselben Wert benutzen; ein
|
|
|
|
|
#: Hygienetest vergleicht sie.
|
|
|
|
@@ -95,6 +96,10 @@ Verwendung: upgrade.sh --app <tesm|tesm-license> [Optionen]
|
|
|
|
|
Vorgabe ist deshalb die Uebernahme.
|
|
|
|
|
--tag <vX.Y.Z> Bestimmte Version installieren (Vorgabe: latest).
|
|
|
|
|
Wird nur beachtet, wenn das Release geladen wird.
|
|
|
|
|
--rollback [pfad] Einen fehlgeschlagenen Lauf zurueckdrehen: die alte
|
|
|
|
|
Installation aus der Sicherung wiederherstellen und
|
|
|
|
|
ihren Dienst wieder einschalten. Ohne Pfad wird die
|
|
|
|
|
neueste Sicherung dieses Namens genommen.
|
|
|
|
|
--dry-run Nur zeigen, was geschehen wuerde
|
|
|
|
|
--yes Keine Rueckfrage
|
|
|
|
|
-h, --help Diese Hilfe
|
|
|
|
@@ -122,6 +127,11 @@ while [[ $# -gt 0 ]]; do
|
|
|
|
|
--new-key) ADOPT_KEY=0; shift ;;
|
|
|
|
|
--adopt-key) ADOPT_KEY=1; shift ;; # Vorgabe, hier nur zur Deutlichkeit
|
|
|
|
|
--tag) TAG="${2:?}"; shift 2 ;;
|
|
|
|
|
--rollback)
|
|
|
|
|
# Der Pfad ist optional: allein genommen heisst es "die neueste".
|
|
|
|
|
if [[ -n "${2:-}" && "${2:-}" != --* ]]; then ROLLBACK="$2"; shift 2
|
|
|
|
|
else ROLLBACK="auto"; shift; fi
|
|
|
|
|
;;
|
|
|
|
|
--dry-run) DRY_RUN=1; shift ;;
|
|
|
|
|
--yes|-y) ASSUME_YES=1; shift ;;
|
|
|
|
|
-h|--help) usage; exit 0 ;;
|
|
|
|
@@ -132,6 +142,144 @@ done
|
|
|
|
|
[[ "$APP" == "tesm" || "$APP" == "tesm-license" ]] || { usage; fail "--app fehlt oder ist unbekannt"; }
|
|
|
|
|
[[ "$(id -u)" -eq 0 ]] || fail "bitte mit sudo ausfuehren"
|
|
|
|
|
|
|
|
|
|
NAME="$APP"
|
|
|
|
|
[[ -n "$INSTANCE" ]] && NAME="$APP-$INSTANCE"
|
|
|
|
|
ADMIN="$NAME-admin"
|
|
|
|
|
NEW_ROOT="/srv/$NAME"
|
|
|
|
|
STAMP="$(date +%Y%m%d-%H%M%S)"
|
|
|
|
|
BACKUP="/srv/$NAME-upgrade-$STAMP"
|
|
|
|
|
ALT_KOPIE="$BACKUP/alt"
|
|
|
|
|
SYSTEM_KOPIE="$BACKUP/system"
|
|
|
|
|
EXPORT_ALT="$BACKUP/export-alt.json"
|
|
|
|
|
IMPORT_NEU="$BACKUP/import-neu.json"
|
|
|
|
|
|
|
|
|
|
# Alte Einheiten der Vorgaengerfassung. Der Timer gehoert dazu: nur den Dienst
|
|
|
|
|
# zu stoppen liesse ihn beim naechsten Ablauf wieder anlaufen.
|
|
|
|
|
# -- Rueckweg ---------------------------------------------------------------- #
|
|
|
|
|
# Alles, was install.sh unter demselben Namen ueberschreiben wuerde. Bei einem
|
|
|
|
|
# Upgrade in dasselbe Verzeichnis sind das die Dateien der alten Fassung.
|
|
|
|
|
SYSTEMDATEIEN=(
|
|
|
|
|
"/etc/systemd/system/$NAME.service"
|
|
|
|
|
"/etc/systemd/system/$NAME-monitor.service"
|
|
|
|
|
"/etc/nginx/sites-available/$NAME"
|
|
|
|
|
"/etc/logrotate.d/$NAME"
|
|
|
|
|
"/etc/update-motd.d/50-$NAME"
|
|
|
|
|
"/etc/tesm/$NAME.env"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
zurueckrollen() {
|
|
|
|
|
local sicherung="$1" grund="${2:-}"
|
|
|
|
|
local alt="$sicherung/alt" system="$sicherung/system"
|
|
|
|
|
[[ -d "$alt" ]] || fail "In $sicherung fehlt das Verzeichnis 'alt' -- das ist keine Sicherung dieses Skripts."
|
|
|
|
|
|
|
|
|
|
# Quelle und Art des Umzugs stehen im Manifest. Aus dem laufenden Aufruf
|
|
|
|
|
# abzuleiten waere falsch: ein Rueckweg kann Tage spaeter und mit anderen
|
|
|
|
|
# Schaltern aufgerufen werden -- und beim automatischen Rueckweg steht
|
|
|
|
|
# IN_PLACE zwar fest, beim spaeteren --rollback aber nicht.
|
|
|
|
|
local ziel="${SOURCE:-}" gleiches_verzeichnis="${IN_PLACE:-0}" vermerkt
|
|
|
|
|
if [[ -f "$system/manifest" ]]; then
|
|
|
|
|
vermerkt="$(awk '$1=="quelle" {print $2}' "$system/manifest" | head -1)"
|
|
|
|
|
[[ -n "$vermerkt" ]] && ziel="$vermerkt"
|
|
|
|
|
vermerkt="$(awk '$1=="in-place" {print $2}' "$system/manifest" | head -1)"
|
|
|
|
|
[[ -n "$vermerkt" ]] && gleiches_verzeichnis="$vermerkt"
|
|
|
|
|
fi
|
|
|
|
|
[[ -n "$ziel" ]] || fail "Im Manifest fehlt die Quelle -- bitte --source angeben."
|
|
|
|
|
|
|
|
|
|
[[ -n "$grund" ]] && warn "$grund"
|
|
|
|
|
step "Rueckweg: alten Stand wiederherstellen"
|
|
|
|
|
|
|
|
|
|
# Der neue Dienst zuerst -- er haelt sonst Dateien offen, die gleich ersetzt
|
|
|
|
|
# werden.
|
|
|
|
|
for unit in "$NAME.service" "$NAME-monitor.service"; do
|
|
|
|
|
if systemctl list-unit-files "$unit" --no-legend 2>/dev/null | grep -q .; then
|
|
|
|
|
systemctl disable --now "$unit" >/dev/null 2>&1 || true
|
|
|
|
|
info "$unit gestoppt"
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
# Verzeichnis: nur bei gleichem Ziel -- bei einer eigenen Instanz war die
|
|
|
|
|
# alte Installation nie angefasst.
|
|
|
|
|
if [[ "$gleiches_verzeichnis" == "1" ]]; then
|
|
|
|
|
rm -rf "$ziel"
|
|
|
|
|
mkdir -p "$ziel"
|
|
|
|
|
tar -C "$alt" -cf - . | tar -C "$ziel" -xf -
|
|
|
|
|
info "$ziel aus der Sicherung wiederhergestellt"
|
|
|
|
|
[[ -d "$ziel/venv" ]] || warn "Im Backup war kein venv -- der alte Dienst braucht dann noch 'python3 -m venv venv' und seine requirements.txt."
|
|
|
|
|
else
|
|
|
|
|
info "$ziel war nicht betroffen (eigene Instanz) -- bleibt, wie es ist"
|
|
|
|
|
if [[ -d "$NEW_ROOT" && "$NEW_ROOT" != "$ziel" ]]; then
|
|
|
|
|
rm -rf "$NEW_ROOT"
|
|
|
|
|
info "$NEW_ROOT entfernt"
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Systemdateien zurueck, alles andere entfernen, was der Lauf angelegt hat.
|
|
|
|
|
local site_wieder=0
|
|
|
|
|
if [[ -f "$system/manifest" ]]; then
|
|
|
|
|
while read -r zeile; do
|
|
|
|
|
case "$zeile" in
|
|
|
|
|
unit-enabled\ *|site-enabled\ *) continue ;;
|
|
|
|
|
esac
|
|
|
|
|
local name; name="$(basename "$zeile")"
|
|
|
|
|
if [[ -e "$system/$name" ]]; then
|
|
|
|
|
cp -a "$system/$name" "$zeile"
|
|
|
|
|
info "wiederhergestellt: $zeile"
|
|
|
|
|
[[ "$zeile" == /etc/nginx/* ]] && site_wieder=1
|
|
|
|
|
fi
|
|
|
|
|
done < <(grep -v '^\(unit\|site\)-enabled ' "$system/manifest" || true)
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
systemctl daemon-reload
|
|
|
|
|
if [[ $site_wieder -eq 1 ]] || [[ -e "/etc/nginx/sites-enabled/$NAME" ]]; then
|
|
|
|
|
nginx -t >/dev/null 2>&1 && systemctl reload nginx >/dev/null 2>&1 \
|
|
|
|
|
&& info "nginx neu geladen" || warn "nginx meldet einen Fehler -- bitte 'nginx -t' ansehen"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Und die Dienste wieder einschalten, die vorher liefen.
|
|
|
|
|
if [[ -f "$system/manifest" ]]; then
|
|
|
|
|
while read -r _ unit; do
|
|
|
|
|
systemctl enable --now "$unit" >/dev/null 2>&1 \
|
|
|
|
|
&& info "$unit wieder eingeschaltet" || warn "$unit liess sich nicht starten"
|
|
|
|
|
done < <(grep '^unit-enabled ' "$system/manifest" || true)
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
step "Zurueckgerollt"
|
|
|
|
|
info "Sicherung bleibt liegen: $sicherung"
|
|
|
|
|
# Nicht ueber ALTE_UNITS: die Liste entsteht erst nach der Quellensuche, und
|
|
|
|
|
# bei "--rollback" laeuft diese Funktion vorher. Das Manifest weiss es.
|
|
|
|
|
local hinweis
|
|
|
|
|
hinweis="$(awk '$1=="unit-enabled" {print $2; exit}' "$system/manifest" 2>/dev/null || true)"
|
|
|
|
|
info "Zustand pruefen: systemctl status ${hinweis:-$APP.service}"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
neueste_sicherung() {
|
|
|
|
|
local kandidat
|
|
|
|
|
kandidat="$(ls -1dt /srv/"$NAME"-upgrade-*/ 2>/dev/null | head -1)"
|
|
|
|
|
[[ -n "$kandidat" ]] || return 1
|
|
|
|
|
printf '%s' "${kandidat%/}"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if [[ -n "$ROLLBACK" ]]; then
|
|
|
|
|
if [[ "$ROLLBACK" == "auto" ]]; then
|
|
|
|
|
ROLLBACK="$(neueste_sicherung)" || fail "Keine Sicherung unter /srv/$NAME-upgrade-* gefunden. Pfad angeben."
|
|
|
|
|
info "Neueste Sicherung: $ROLLBACK"
|
|
|
|
|
fi
|
|
|
|
|
[[ -d "$ROLLBACK" ]] || fail "$ROLLBACK gibt es nicht"
|
|
|
|
|
if [[ $DRY_RUN -eq 1 ]]; then
|
|
|
|
|
step "--dry-run: es wuerde $ROLLBACK zurueckgerollt."
|
|
|
|
|
exit 0
|
|
|
|
|
fi
|
|
|
|
|
if [[ $ASSUME_YES -eq 0 ]]; then
|
|
|
|
|
read -r -p "Stand aus $ROLLBACK wiederherstellen? [j/N] " answer
|
|
|
|
|
[[ "$answer" =~ ^[jJyY]$ ]] || { echo "Abgebrochen."; exit 0; }
|
|
|
|
|
fi
|
|
|
|
|
zurueckrollen "$ROLLBACK"
|
|
|
|
|
exit 0
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Ab hier wird wirklich installiert -- ein Rueckweg hat oben schon
|
|
|
|
|
# beendet. Erst jetzt braucht es ein Release und eine Quelle.
|
|
|
|
|
|
|
|
|
|
# --8<-- Bootstrap: Release holen --------------------------------------------
|
|
|
|
|
# Wortgleich in update.sh und upgrade.sh; ein Hygienetest vergleicht die beiden
|
|
|
|
|
# Bloecke. Zwei eigenstaendige Skripte koennen sich keine Datei teilen, und
|
|
|
|
@@ -255,28 +403,55 @@ fi
|
|
|
|
|
[[ -d "$SOURCE" ]] || fail "Die alte Installation $SOURCE gibt es nicht (--source setzen)"
|
|
|
|
|
ist_alte_fassung "$SOURCE" || fail "In $SOURCE liegt keine sqlite.db -- das ist keine Installation der Vorgaengerfassung"
|
|
|
|
|
|
|
|
|
|
NAME="$APP"
|
|
|
|
|
[[ -n "$INSTANCE" ]] && NAME="$APP-$INSTANCE"
|
|
|
|
|
ADMIN="$NAME-admin"
|
|
|
|
|
NEW_ROOT="/srv/$NAME"
|
|
|
|
|
IN_PLACE=0
|
|
|
|
|
[[ "$(cd "$SOURCE" && pwd)" == "$NEW_ROOT" ]] && IN_PLACE=1
|
|
|
|
|
|
|
|
|
|
STAMP="$(date +%Y%m%d-%H%M%S)"
|
|
|
|
|
BACKUP="/srv/$NAME-upgrade-$STAMP"
|
|
|
|
|
ALT_KOPIE="$BACKUP/alt"
|
|
|
|
|
EXPORT_ALT="$BACKUP/export-alt.json"
|
|
|
|
|
IMPORT_NEU="$BACKUP/import-neu.json"
|
|
|
|
|
# Die Units der alten Fassung erkennt man daran, dass sie in genau dieses
|
|
|
|
|
# Verzeichnis zeigen -- nicht am Namen der Anwendung. Nach einem rename.sh
|
|
|
|
|
# heisst die *laufende* Installation "tesm", und eine Namensliste haette sie
|
|
|
|
|
# gestoppt und deaktiviert, sobald jemand die archivierte 1.x in eine eigene
|
|
|
|
|
# Instanz hochzieht.
|
|
|
|
|
#
|
|
|
|
|
# Timer und Hilfsdienste tragen keinen Pfad (der Restart-Timer ruft nur
|
|
|
|
|
# "systemctl restart ..."). Sie kommen ueber den Namen der gefundenen Unit mit.
|
|
|
|
|
alte_units_finden() {
|
|
|
|
|
local quelle="$1" gefunden=() datei name runde
|
|
|
|
|
shopt -s nullglob
|
|
|
|
|
for datei in /etc/systemd/system/*.service; do
|
|
|
|
|
grep -qs -- "$quelle/" "$datei" && gefunden+=("$(basename "$datei")")
|
|
|
|
|
done
|
|
|
|
|
# Zwei Runden: erst Timer und Helfer, die eine gefundene Unit nennen, dann
|
|
|
|
|
# noch einmal fuer deren eigene Timer.
|
|
|
|
|
for runde in 1 2; do
|
|
|
|
|
for datei in /etc/systemd/system/*.service /etc/systemd/system/*.timer; do
|
|
|
|
|
name="$(basename "$datei")"
|
|
|
|
|
[[ " ${gefunden[*]-} " == *" $name "* ]] && continue
|
|
|
|
|
for treffer in ${gefunden[*]-}; do
|
|
|
|
|
if grep -qs -- "$treffer" "$datei"; then gefunden+=("$name"); break; fi
|
|
|
|
|
done
|
|
|
|
|
done
|
|
|
|
|
done
|
|
|
|
|
shopt -u nullglob
|
|
|
|
|
printf '%s\n' ${gefunden[*]-}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Alte Einheiten der Vorgaengerfassung. Der Timer gehoert dazu: nur den Dienst
|
|
|
|
|
# zu stoppen liesse ihn beim naechsten Ablauf wieder anlaufen.
|
|
|
|
|
if [[ "$APP" == "tesm" ]]; then
|
|
|
|
|
ALTE_UNITS=(tesm.service tesm-check.timer tesm-check.service
|
|
|
|
|
tesm-check-restart.timer tesm-check-restart.service)
|
|
|
|
|
else
|
|
|
|
|
ALTE_UNITS=(tesm-license.service)
|
|
|
|
|
mapfile -t ALTE_UNITS < <(alte_units_finden "$SOURCE")
|
|
|
|
|
if [[ ${#ALTE_UNITS[@]} -eq 0 ]]; then
|
|
|
|
|
if [[ "$SOURCE" == "/srv/$APP" ]]; then
|
|
|
|
|
# Kein Fund, aber die Quelle ist der Hauptpfad: die historischen Namen der
|
|
|
|
|
# Fassung 1.x als Rueckfall.
|
|
|
|
|
if [[ "$APP" == "tesm" ]]; then
|
|
|
|
|
ALTE_UNITS=(tesm.service tesm-check.timer tesm-check.service
|
|
|
|
|
tesm-check-restart.timer tesm-check-restart.service)
|
|
|
|
|
else
|
|
|
|
|
ALTE_UNITS=(tesm-license.service)
|
|
|
|
|
fi
|
|
|
|
|
else
|
|
|
|
|
ALTE_UNITS=()
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
step "Vorhaben"
|
|
|
|
|
info "Anwendung : $APP${INSTANCE:+ (Instanz $INSTANCE)}"
|
|
|
|
|
info "Neue Fassung : $RELEASE_HERKUNFT"
|
|
|
|
@@ -302,15 +477,44 @@ fi
|
|
|
|
|
|
|
|
|
|
# -- 1. Sichern -------------------------------------------------------------- #
|
|
|
|
|
step "Sichern"
|
|
|
|
|
mkdir -p "$ALT_KOPIE"
|
|
|
|
|
mkdir -p "$ALT_KOPIE" "$SYSTEM_KOPIE"
|
|
|
|
|
chmod 700 "$BACKUP"
|
|
|
|
|
# -a: Rechte und Zeiten bleiben, damit die Kopie auch als Rueckweg taugt.
|
|
|
|
|
# Das venv der alten Installation bleibt aussen vor -- es ist nachbaubar,
|
|
|
|
|
# gross, und seine Shebangs zeigen ohnehin auf den alten Pfad.
|
|
|
|
|
tar -C "$SOURCE" --exclude=venv --exclude=__pycache__ -cf - . | tar -C "$ALT_KOPIE" -xf -
|
|
|
|
|
info "$(du -sh "$ALT_KOPIE" | cut -f1) kopiert (ohne venv)"
|
|
|
|
|
|
|
|
|
|
# Das venv kommt nur mit, wenn in dasselbe Verzeichnis installiert wird -- dort
|
|
|
|
|
# ersetzt install.sh es, und ohne das alte startet der alte Dienst nach einem
|
|
|
|
|
# Rueckweg nicht mehr. Bei einer eigenen Instanz bleibt die alte Installation
|
|
|
|
|
# unangetastet, dann waere es nur Ballast (und seine Shebangs zeigen auf einen
|
|
|
|
|
# anderen Pfad).
|
|
|
|
|
if [[ $IN_PLACE -eq 1 ]]; then
|
|
|
|
|
tar -C "$SOURCE" --exclude=__pycache__ -cf - . | tar -C "$ALT_KOPIE" -xf -
|
|
|
|
|
info "$(du -sh "$ALT_KOPIE" | cut -f1) kopiert (mit venv, weil dasselbe Verzeichnis)"
|
|
|
|
|
else
|
|
|
|
|
tar -C "$SOURCE" --exclude=venv --exclude=__pycache__ -cf - . | tar -C "$ALT_KOPIE" -xf -
|
|
|
|
|
info "$(du -sh "$ALT_KOPIE" | cut -f1) kopiert (ohne venv)"
|
|
|
|
|
fi
|
|
|
|
|
[[ -f "$ALT_KOPIE/sqlite.db" ]] || fail "In der Kopie fehlt die Datenbank -- Abbruch"
|
|
|
|
|
|
|
|
|
|
# Und die Systemdateien: bei gleichem Verzeichnis schreibt install.sh Unit,
|
|
|
|
|
# nginx-Site, logrotate und Banner neu. Ohne Kopie liesse sich der alte Stand
|
|
|
|
|
# nicht wiederherstellen -- das Verzeichnis allein genuegt nicht.
|
|
|
|
|
: > "$SYSTEM_KOPIE/manifest"
|
|
|
|
|
# Woher kam der Stand, und ging es in dasselbe Verzeichnis? Ein spaeterer
|
|
|
|
|
# Rueckweg darf das nicht raten muessen -- er laeuft womoeglich Tage danach
|
|
|
|
|
# und mit anderen Schaltern.
|
|
|
|
|
printf 'quelle %s\n' "$SOURCE" >> "$SYSTEM_KOPIE/manifest"
|
|
|
|
|
printf 'in-place %s\n' "$IN_PLACE" >> "$SYSTEM_KOPIE/manifest"
|
|
|
|
|
for pfad in "${SYSTEMDATEIEN[@]}"; do
|
|
|
|
|
[[ -e "$pfad" ]] || continue
|
|
|
|
|
cp -a "$pfad" "$SYSTEM_KOPIE/$(basename "$pfad")"
|
|
|
|
|
printf '%s\n' "$pfad" >> "$SYSTEM_KOPIE/manifest"
|
|
|
|
|
done
|
|
|
|
|
# Welche Units liefen, und war die Site eingeschaltet?
|
|
|
|
|
for unit in "${ALTE_UNITS[@]}"; do
|
|
|
|
|
systemctl is-enabled "$unit" >/dev/null 2>&1 && printf 'unit-enabled %s\n' "$unit" >> "$SYSTEM_KOPIE/manifest"
|
|
|
|
|
done
|
|
|
|
|
[[ -L "/etc/nginx/sites-enabled/$NAME" ]] && printf 'site-enabled %s\n' "$NAME" >> "$SYSTEM_KOPIE/manifest"
|
|
|
|
|
info "$(grep -c . "$SYSTEM_KOPIE/manifest") Systemdatei(en) und Zustaende vermerkt"
|
|
|
|
|
|
|
|
|
|
# -- 2. Altes System abschalten ---------------------------------------------- #
|
|
|
|
|
if [[ $STOP_OLD -eq 1 ]]; then
|
|
|
|
|
step "Altes System abschalten"
|
|
|
|
@@ -328,7 +532,13 @@ fi
|
|
|
|
|
step "Neu installieren"
|
|
|
|
|
INSTALL_ARGS=(--app "$APP" --yes)
|
|
|
|
|
[[ -n "$INSTANCE" ]] && INSTALL_ARGS+=(--instance "$INSTANCE")
|
|
|
|
|
bash "$SRC/deploy/install.sh" "${INSTALL_ARGS[@]}" ${EXTRA[0]+"${EXTRA[@]}"}
|
|
|
|
|
if ! bash "$SRC/deploy/install.sh" "${INSTALL_ARGS[@]}" ${EXTRA[0]+"${EXTRA[@]}"}; then
|
|
|
|
|
# Hier stand das System bisher halb umgebaut da: alter Dienst aus, neuer
|
|
|
|
|
# nicht vorhanden. Der Rueckweg bringt es in den Zustand von vorher, damit
|
|
|
|
|
# ein zweiter Versuch nach der Ursache moeglich ist.
|
|
|
|
|
zurueckrollen "$BACKUP" "Die Installation ist fehlgeschlagen."
|
|
|
|
|
fail "Upgrade abgebrochen und zurueckgerollt. Ursache oben nachsehen, dann erneut versuchen."
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [[ $WITH_DATA -eq 0 ]]; then
|
|
|
|
|
step "Fertig -- ohne Datenuebernahme"
|
|
|
|
|