Files
datensicherung_rsync/README.md
T

256 lines
9.3 KiB
Markdown
Raw Normal View History

2026-04-28 10:42:31 +02:00
# README Snapshot-Backup mit rsync
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Dieses Skript erstellt Snapshots des Home-Verzeichnisses mit `rsync` und `--link-dest`.[cite:43][cite:34] Jeder Snapshot sieht wie ein vollständiges Backup aus, aber unveränderte Dateien werden per Hardlink wiederverwendet, sodass Speicherplatz gespart wird.[cite:34][cite:92]
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
## Zweck
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Das Skript sichert den Inhalt von `HOME` auf ein externes Zielverzeichnis und legt dabei zeitgestempelte Snapshot-Ordner an.[cite:43] Über den Symlink `latest` wird immer auf den zuletzt erfolgreichen Sicherungsstand verwiesen.[cite:34][cite:92]
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Typische Vorteile dieses Ansatzes:
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
- Einfach browsebare Backups, weil jeder Snapshot als normales Verzeichnis vorliegt.[cite:43][cite:91]
- Platzersparnis durch Hardlinks mit `--link-dest`.[cite:34][cite:92]
- Aufbewahrung mehrerer Sicherungsstände durch Rotation älterer Snapshots.[cite:43]
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
## Voraussetzungen
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Für `--link-dest` sollte das Ziel auf einem Linux-Dateisystem liegen, das Hardlinks sauber unterstützt, etwa ext4, XFS oder btrfs.[cite:34][cite:91] Dateisysteme wie exFAT sind für diese Snapshot-Technik ungeeignet.[cite:34]
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Benötigte Werkzeuge:
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
- `bash`
- `rsync`
- `readlink`
- `tee`
- Standard-Tools wie `mkdir`, `ln`, `ls`, `tail`, `rm`
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
## Verzeichnisaufbau
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Das Skript erzeugt pro Lauf einen neuen Snapshot mit Zeitstempel.[cite:43][cite:92]
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Beispiel:
```text
/run/media/hans/usbsicherung/jacboy_sicherung/
└── <hostname>/
├── 2026-04-28_10-30-00/
├── 2026-04-29_10-30-00/
├── latest -> /run/media/hans/usbsicherung/jacboy_sicherung/<hostname>/2026-04-29_10-30-00
└── logs/
```
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
## Funktionsweise
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Das Skript prüft zunächst, ob das Zielverzeichnis existiert und beschreibbar ist, und legt anschließend Snapshot- und Log-Verzeichnisse an.[cite:43][cite:97] Danach wird `rsync` mit Archivoptionen sowie Ausschlüssen für nicht benötigte Verzeichnisse ausgeführt.[cite:43][cite:91]
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Wenn bereits ein gültiger vorheriger Snapshot existiert, wird dieser über `--link-dest` als Referenz verwendet.[cite:34][cite:92] Unveränderte Dateien werden dann nicht erneut kopiert, sondern als Hardlinks im neuen Snapshot eingebunden.[cite:34]
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Nach erfolgreichem Lauf aktualisiert das Skript den Symlink `latest` und entfernt ältere Snapshots oberhalb des konfigurierten Aufbewahrungswerts `KEEP`.[cite:43]
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
## Verwendete rsync-Optionen
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
| Option | Bedeutung |
|---|---|
| `-a` | Archivmodus: rekursiv kopieren und Metadaten erhalten.[cite:91][cite:43] |
| `-H` | Hardlinks in der Quelle erhalten.[cite:91] |
| `-A` | ACLs mitnehmen, sofern vorhanden.[cite:91] |
| `-X` | Erweiterte Attribute mitnehmen.[cite:91] |
| `-x` | Auf demselben Dateisystem bleiben; zusätzliche Mounts unterhalb von `HOME` werden nicht traversiert.[cite:91][cite:43] |
| `--delete` | Entfernt Dateien im neuen Snapshot, die in der Quelle nicht mehr vorhanden sind; ältere Snapshots bleiben dabei unberührt.[cite:91][cite:34] |
| `--delete-excluded` | Entfernt auch explizit ausgeschlossene Inhalte aus dem Ziel-Snapshot.[cite:91] |
| `--link-dest` | Verweist auf den letzten Snapshot, damit unveränderte Dateien per Hardlink wiederverwendet werden.[cite:34][cite:92] |
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
## Anpassbare Variablen
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Die wichtigsten Variablen stehen am Anfang des Skripts:
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
```bash
SRC="${HOME}/"
DEST_BASE="/run/media/hans/usbsicherung/jacboy_sicherung"
KEEP=30
```
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
- `SRC`: Quellverzeichnis, standardmäßig das eigene Home-Verzeichnis.
- `DEST_BASE`: Basisverzeichnis auf dem Backup-Medium.
- `KEEP`: Anzahl der Snapshots, die aufbewahrt werden sollen.
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Auch die Ausschlussliste kann direkt im Array `EXCLUDES` angepasst werden, zum Beispiel für Cache-, Download- oder temporäre Verzeichnisse.[cite:43]
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
## Verwendung
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Syntax prüfen:
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
```bash
bash -n sicherung.sh
```
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Skript ausführen:
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
```bash
bash sicherung.sh
```
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Für einen sicheren Test kann vorübergehend `--dry-run` in die `RSYNC_OPTS` aufgenommen werden; dann zeigt `rsync` nur an, was passieren würde, ohne tatsächlich Daten zu schreiben.[cite:91][cite:43]
2026-04-28 11:16:43 +02:00
## Wiederherstellungstest
Ein Backup gilt erst dann als verlässlich, wenn sich Daten daraus testweise wiederherstellen und inhaltlich prüfen lassen.[cite:105][cite:109] Der empfohlene Weg ist, einen Snapshot nicht direkt ins echte Home-Verzeichnis zurückzuschreiben, sondern zunächst in ein separates Testverzeichnis zu restaurieren.[cite:105][cite:107]
### Testverzeichnis anlegen
```bash
mkdir -p /tmp/restore-test-home
```
### Snapshot auswählen und zurückspielen
Beispiel für einen Restore eines bestimmten Snapshots:
```bash
SNAP="/run/media/hans/usbsicherung/jacboy_sicherung/$(hostname -s)/2026-04-28_10-30-00"
rsync -aHAX \
"${SNAP}/" \
/tmp/restore-test-home/
```
Damit werden die Daten aus dem Snapshot mit Rechten, ACLs und erweiterten Attributen in das Testziel kopiert.[cite:91][cite:43] Alternativ kann auch nur ein Teilbereich wie `Documents/`, ein Projektordner oder `.config/` restauriert werden, um einzelne Anwendungsszenarien gezielt zu prüfen.[cite:105][cite:107]
### Integrität prüfen
Nach dem Restore sollten mehrere Prüfungen erfolgen:[cite:105][cite:110]
- Wichtige Dateien öffnen, etwa Dokumente, PDFs, Bilder oder Quellcode.[cite:105]
- Anwendungen testweise mit restaurierten Daten starten, zum Beispiel ein Projekt im Editor oder eine Konfiguration in einem Testprofil.[cite:107]
- Für wichtige Dateien Checksummen vergleichen, um die inhaltliche Identität sicherzustellen.[cite:110]
Beispiel mit `sha256sum`:
```bash
cd "${HOME}"
sha256sum wichtige_datei.odt
cd /tmp/restore-test-home
sha256sum wichtige_datei.odt
```
Die Prüfsummen sollten identisch sein.[cite:110]
### Worauf beim Restore zu achten ist
Beim Restore-Test sollten insbesondere Dateirechte, Symlinks, ACLs, xattrs und eventuelle Fehlermeldungen von `rsync` geprüft werden.[cite:91][cite:105] Gerade bei einem Restore auf ein anderes Dateisystem kann es Einschränkungen bei ACLs oder erweiterten Attributen geben.[cite:91]
### Empfehlung für die Praxis
Sinnvoll ist ein regelmäßiger Wiederherstellungstest, zum Beispiel quartalsweise, mit kurzer Dokumentation: verwendeter Snapshot, Testziel, geprüfte Dateien, Ergebnis und Auffälligkeiten.[cite:105][cite:109] Erst ein erfolgreich getesteter Restore macht aus einem Backup eine belastbare Datensicherung.[cite:105]
2026-04-28 10:42:31 +02:00
## Beispielskript
```bash
#!/usr/bin/env bash
set -Eeuo pipefail
SRC="${HOME}/"
DEST_BASE="/run/media/hans/usbsicherung/jacboy_sicherung"
HOST="$(hostname -s)"
STAMP="$(date +%F_%H-%M-%S)"
SNAPSHOT_DIR="${DEST_BASE}/${HOST}/${STAMP}"
LAST_LINK="${DEST_BASE}/${HOST}/latest"
LOG_DIR="${DEST_BASE}/${HOST}/logs"
LOG_FILE="${LOG_DIR}/backup-${STAMP}.log"
KEEP=30
log() {
local msg="[$(date +%F\ %T)] $*"
echo "${msg}"
if [[ -n "${LOG_FILE:-}" ]]; then
mkdir -p "$(dirname "${LOG_FILE}")"
echo "${msg}" >> "${LOG_FILE}"
fi
}
fail() {
log "FEHLER: $*"
exit 1
}
if [[ ! -d "${DEST_BASE}" ]]; then
fail "Zielbasis ${DEST_BASE} existiert nicht oder ist nicht gemountet. Bitte USB-Laufwerk prüfen."
fi
if [[ ! -w "${DEST_BASE}" ]]; then
fail "Zielbasis ${DEST_BASE} ist nicht beschreibbar. Rechte/Mount prüfen."
fi
mkdir -p "${SNAPSHOT_DIR}" "${LOG_DIR}"
log "Starte Backup: ${SRC} -> ${SNAPSHOT_DIR}"
RSYNC_OPTS=(
-aHAXx
--numeric-ids
--delete
--delete-excluded
--info=stats2,progress2
--human-readable
--partial
)
EXCLUDES=(
--exclude=".cache/"
--exclude="Downloads/"
--exclude=".local/share/Trash/"
--exclude=".gvfs/"
--exclude=".dotnet/"
--exclude=".codegpt/"
--exclude=".copilot/"
--exclude=".var/"
--exclude=".vscode/"
--exclude="temp/"
)
if [[ -L "${LAST_LINK}" ]] && [[ -d "$(readlink -f "${LAST_LINK}")" ]]; then
RSYNC_OPTS+=(--link-dest="$(readlink -f "${LAST_LINK}")")
log "Verwende link-dest: $(readlink -f "${LAST_LINK}")"
else
log "Kein gültiger letzter Snapshot gefunden es wird ein vollständiger Lauf erstellt."
fi
if rsync "${RSYNC_OPTS[@]}" \
"${EXCLUDES[@]}" \
"${SRC}" "${SNAPSHOT_DIR}/" | tee -a "${LOG_FILE}"
then
log "rsync erfolgreich abgeschlossen."
else
fail "rsync ist mit einem Fehler beendet worden."
fi
ln -sfn "${SNAPSHOT_DIR}" "${LAST_LINK}"
log "latest-Link zeigt jetzt auf ${SNAPSHOT_DIR}"
cd "${DEST_BASE}/${HOST}"
SNAPS=(20*/)
if (( ${#SNAPS[@]} > KEEP )); then
log "Rotationslauf: Es existieren ${#SNAPS[@]} Snapshots, KEEP=${KEEP}."
ls -1dt 20*/ | tail -n +$((KEEP + 1)) | while read -r old; do
log "Lösche alten Snapshot: ${old}"
rm -rf -- "${old}"
done
else
log "Rotationslauf: Es müssen keine alten Snapshots gelöscht werden (Anzahl: ${#SNAPS[@]}, KEEP=${KEEP})."
fi
log "Backup abgeschlossen."
```
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
## Sicherheitshinweise
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Ein erster Testlauf sollte als Dry-Run erfolgen, um Ausschlüsse, Zielpfad und Verhalten zu prüfen, bevor echte Daten geschrieben oder gelöscht werden.[cite:91][cite:43] Das Zielverzeichnis sollte nicht innerhalb des zu sichernden Home-Verzeichnisses liegen, um Rekursionen und ungewollte Mitsicherungen zu vermeiden.[cite:43]
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Bei Verwendung von `--delete` gilt: Gelöschte Dateien verschwinden aus dem neu erzeugten Snapshot, bleiben aber in älteren Snapshots weiterhin vorhanden.[cite:34][cite:92] Genau dadurch entsteht die gewünschte Snapshot-Historie.[cite:92]
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
## Mögliche Erweiterungen
2026-04-28 08:34:58 +00:00
2026-04-28 10:42:31 +02:00
Sinnvolle nächste Ausbaustufen wären ein optionaler `--dry-run`-Schalter, eine Prüfung des tatsächlichen Mountpoints per `mountpoint`, sowie eine Automatisierung über `systemd`-Timer statt manueller Ausführung.[cite:97][cite:43]