Guard writer units against activation and fix backup cancellation
This commit is contained in:
1 parent
c0a24b63fc
commit
ff152c7f0f
9 files changed
+372
-16
No files matched your search
+59
-1
@@ -201,6 +201,40 @@ Gitea: `APP_DATA_PATH`, `[repository] ROOT`, Custom-Verzeichnis und `app.ini` pr
|
||||
|
||||
`MAIL_BACKUP_MODE=live` und abgeschaltete Stopps sind bewusste Ausnahmen mit Konsistenzrisiko. Das Log weist darauf hin. Home-Verzeichnisse werden mit `--one-file-system` kopiert: Daten anderer Mounts fehlen dann absichtlich. Mailqueues, zusätzliche Spamfilter-/DKIM-Verzeichnisse oder Maildatenbanken sind nur gesichert, wenn sie explizit im Umfang stehen.
|
||||
|
||||
Ein einfacher `systemctl stop` verhindert keinen späteren Start durch andere
|
||||
Aufträge. Auf Gemini starteten am 10.09.2026 um 15:15:00 Uhr Apache und PHP-FPM
|
||||
während der bis mindestens 15:16:33 laufenden Nextcloud-Datenkopie erneut. Die
|
||||
Starts erfolgten vor der Wiederaufnahme durch das Backup. Dieser Lauf erfüllt
|
||||
die vereinbarte Konsistenzbedingung nicht; eine erfolgreiche Hash-/Remote-Prüfung
|
||||
kann dies nicht nachträglich beweisen. Der auslösende Auftrag ist noch unbekannt.
|
||||
|
||||
Vor dem Stoppen erhält nun jeder konfigurierte Writer eine eigene temporäre
|
||||
systemd-Ergänzung unter `/run/systemd/system/UNIT.d/zzzz-app-backup-LAUF.conf`.
|
||||
`ConditionPathExists=!/run/app-backup-guard-ZUFALL` verhindert den Start, solange
|
||||
das zugehörige Verzeichnis besteht. Das gilt auch für zuvor inaktive konfigurierte
|
||||
Writer und für Dienste mit eigener Unit-Datei unter `/etc`. Bestehende Maskierungen
|
||||
werden nicht verändert. Die Laufzeitergänzung muss nach `daemon-reload` als letztes
|
||||
Drop-in gemeldet werden; andernfalls bricht der Lauf ab, damit spätere
|
||||
Condition-Resets die Sperre nicht unbemerkt überschreiben.
|
||||
|
||||
Nach dem Anhalten aller Writer, vor und nach den Dumps/Dateikopien und unmittelbar
|
||||
vor der Freigabe prüft das Backup Dienstzustand, eigene Sperrdateien und die
|
||||
systemd-Zeitpunkte `ActiveEnterTimestampMonotonic` und `InactiveExitTimestampMonotonic`.
|
||||
Eine erkannte Aktivierung, veränderte Sperre oder nicht prüfbarer Zustand führt
|
||||
zum Fehler, bevor Archive als vollständiger Satz veröffentlicht werden. Diese
|
||||
Kontrollen ersetzen keine vollständige Ereignisaufzeichnung und schützen nicht
|
||||
vor nicht konfigurierten Prozessen, direktem Programmstart außerhalb systemd oder
|
||||
gezieltem administrativem Entfernen der Absicherung zwischen zwei Kontrollen.
|
||||
Die systemd-Startbedingung verhindert reguläre Startaufträge während des Fensters.
|
||||
Quelle: [systemd-Startbedingungen](https://github.com/systemd/systemd/blob/v256/man/systemd.unit.xml).
|
||||
|
||||
Bei erfolgreicher Kopie und bei normalen Backupfehlern entfernt der Wiederanlauf
|
||||
ausschließlich die eigenen Drop-ins, lädt systemd neu und entfernt das zugehörige
|
||||
Sperrverzeichnis. Erst danach werden die zuvor aktiven Dienste gestartet; deren
|
||||
aktiver Zustand wird überprüft. Scheitert die Freigabe, bleiben Wiederanlaufdaten
|
||||
erhalten und es wird kein Erfolg gemeldet. Bei teilweise ausgeführtem Restore
|
||||
bleiben die Startsperren zusammen mit dem Wartungsmodus zur manuellen Prüfung bestehen.
|
||||
|
||||
`ENABLE_MAIL_STORE=true` bleibt der kompatible Default: `MAIL_DIR` muss existieren.
|
||||
Bei Mailboxen ausschließlich in Benutzerverzeichnissen kann explizit
|
||||
`ENABLE_MAIL_STORE=false` gesetzt werden. Dann sind aktivierte, nicht leere
|
||||
@@ -250,6 +284,25 @@ Für den täglichen Zeitplan z. B. bei mehr als 36 Stunden ohne erfolgreichen La
|
||||
|
||||
Ein geplanter Backupabbruch erfolgt über `systemctl stop app-backup.service`. Normale INT-/TERM-Behandlung versucht die ursprünglichen Dienste wiederherzustellen. SIGKILL, Kernelabsturz oder Stromverlust können keine Shell-Traps ausführen. Dafür liegt `recovery-LAUFNAME.json` mit vorher aufgezeichnetem Wartungs-/Dienstzustand und Arbeitsordner im Workdir. Diese Datei ist eine manuelle Wiederanlaufhilfe, kein automatischer Neustartauftrag. Das System startet nicht blind Anwendungen über einen teilweise restaurierten Datenbestand.
|
||||
|
||||
Backup-Unit und Update-Auftrag verwenden `KillMode=control-group`: Beim Stoppen
|
||||
erhalten auch laufende Dump-, rsync-, Kompressions- und rclone-Prozesse TERM.
|
||||
Dadurch können die wartenden Shells ihre Fehlerbehandlung ausführen, statt bis
|
||||
zum regulären Ende eines langen Uploads zu warten. Die tee-Prozesse ignorieren
|
||||
INT/TERM und enden mit dem Schließen ihrer Eingabe; so bleibt die Protokollierung
|
||||
während der Wiederaufnahme erhalten. Die fünfminütige Stop-Frist bleibt bestehen.
|
||||
Sie garantiert keine Wiederherstellung bei blockierten Kernelzugriffen oder
|
||||
fehlgeschlagenen Dienststarts. Quelle:
|
||||
[systemd-Signalzustellung](https://github.com/systemd/systemd/blob/v256/man/systemd.kill.xml).
|
||||
|
||||
Die Wiederanlaufdatei enthält außerdem `service_guard_files` und
|
||||
`service_guard_directory`. Bei manueller Wiederherstellung nur die darin genannten
|
||||
eigenen Drop-in-Dateien entfernen, `systemctl daemon-reload` ausführen und danach
|
||||
das zugehörige leere Sperrverzeichnis mit `rmdir` entfernen. Keine fremden Drop-ins
|
||||
oder Maskierungen löschen. Erst nach Prüfung des Datenzustands die aufgezeichneten
|
||||
Dienste und den Wartungsmodus wiederherstellen. Die Sperren liegen unter `/run`
|
||||
und überleben keinen Neustart; ein Reboot ist deshalb keine sichere Reparatur
|
||||
eines teilweise ausgeführten Restores.
|
||||
|
||||
## Wiederherstellung
|
||||
|
||||
### Prüfphase
|
||||
@@ -360,10 +413,15 @@ Die Entfernung der drei DB-Dateien aus dem aktuellen Baum löscht deren Historie
|
||||
|
||||
Reproduzierbar mit `tests/Dockerfile` und `tests/run.sh`. Der Container bekommt das Repository nur lesbar und benötigt während der Tests kein Netzwerk. Die MariaDB läuft ohne TCP-Port in einem temporären Verzeichnis. systemd/occ werden simuliert; alle eigentlichen Archive, Dateikopien, Dumps/Imports und Crypt-Operationen sind real.
|
||||
|
||||
Ergebnis des lokalen Abschlusslaufs am 10.09.2026: **44 Tests erfolgreich**, Shell-Syntax und ShellCheck ohne Befund. Testumgebung: Debian 13.6, MariaDB 11.8.6, rclone 1.60.1-DEV (Distributionspaket), ShellCheck 0.10.0. Diese Versionsangaben beschreiben die Testumgebung, keine Empfehlung für die Produktivversion.
|
||||
Verifikation am 10.09.2026: **52 Testfälle erfolgreich** — 50 im vollständigen Durchlauf, anschließend beide zusätzlichen Abbruchtests für Kopie und Upload auf dem ergänzten Stand. Shell-Syntax und ShellCheck abschließend ohne Befund. Testumgebung: Debian 13.6, MariaDB 11.8.6, rclone 1.60.1-DEV (Distributionspaket), ShellCheck 0.10.0. Diese Versionsangaben beschreiben die Testumgebung, keine Empfehlung für die Produktivversion.
|
||||
|
||||
Geprüfte Fälle umfassen:
|
||||
|
||||
- Fremde Startversuche während realer rsync-Kopien werden durch das systemd-Testmodell übersprungen; zuvor inaktive Writer bleiben nach dem Lauf inaktiv.
|
||||
- Aktive sowie zwischenzeitlich gestartete und wieder gestoppte Writer verhindern die Veröffentlichung eines vollständigen Satzes.
|
||||
- Nicht geladene Startsperre, Erhalt vorhandener Maskierungen und fehlgeschlagene Sperrfreigabe mit erhaltener Wiederanlaufdatei.
|
||||
- Bei teilweise ausgeführtem Restore bleiben eigene Startsperren erhalten. `systemd-analyze` prüft die reale Condition-Auswertung und Unit-Syntax separat, ohne einen Dienst zu starten.
|
||||
- TERM an die gesamte simulierte Unit-Prozessgruppe während blockierter Kopie beziehungsweise blockiertem Upload: zeitnahes Fehlerergebnis, Dienstwiederaufnahme, freigegebene Startsperren, erhaltenes Protokoll und gestoppter Backup-Timer.
|
||||
- Verweigerter rsync-Quellzugriff bricht das Update vor Installation und Dienst-Stopp ab.
|
||||
- Verweigerte Verzeichnisattribute werden vor Wartungsmodus erkannt; der private Prüfbereich wird entfernt.
|
||||
- Attributprobe kopiert keine Kindobjekte; rsync erbt bei Prüfung, Backup und Restore keine Update-/Backup-Sperrdeskriptoren.
|
||||
|
||||
Reference in new issue
Block a user