Snapshots mit Rsync

Das Prinzip

Sinn und Zweck des folgenden Skriptes ist die Bereitstellung von Zuständen dr Dateien zu vergangenen Zeitpunkten. Es soll quasi eine Form des Backups darstellen, das von den Benutzersn des Shares selbst verwendet werden kann. Sinnvollerweise wird dazu auf einem anderen Medium ein Verzeichnis "backup.0" angelegt, auf dem initial alle Daten des Quell-Directories (Hier: "source_directory/") 1:1 mit Berechtigungen und Zeitstempeln kopiert werden.

Das kann entweder mit dem Befehl "cp -rp quelle ziel" geschehen, oder aber mit "rsync -a quelle ziel". Da letzterer auch in dem nachfolgenden Skript verwendet wird, und vor allem auch über Rechnergrenzen hinweg über das SSH-Protokoll funkltioniert, ziehe ich diesen vor. In den nachfolgenden Abgleich-Vorgängen wird rsync verwendet, um die Daten mit der Quelle synchron zu halten. Dabei werden auch die nicht mehr vorhandenen Dateien gelöscht, was mit dem Befehl "rsync -a --delete quelle ziel" geschieht.

Da aber dieses Backup mit dem nächsten Sync-Vorgang gegebenenfalls versehentlich gelöschte Dateien auch auf dem Backup löscht, bietet es sich an, die Zustände dieses Backups in ein oder mehreren Versionen zu archivieren.

In dem nachfolgenden Skript werden 4 Versionen vorgehalten, die backup.0 bis backup.3 benannt werden. Die höchste Zahl gibt dabei das größte Alter der Snapshots an. Dabei wird zunächst das älteste Backup-Verzeichnis gelöscht oder überschrieben, in diesem Fall nach "backup.tmp" umbenannt. die nachfolgenden Backup-Verzeichnisse werden jeweils in ihrer Nummerierung um 1 erhöht.
Zum Schluss wird das backup.tmp in backup.0 umbenannt und mit den bis dahin jüngsten Daten des Backups (jetzt backup.1) versehen, wobei die Dateien nicht wirklich kopiert, sondern nur als Hardlinks angelegt werden. Wo wird für identische Dateien kein weiterer Speicherplatz, sondern nur ein Inode benötigt.
Erst dann werden die Daten aus dem Original nach backup0 Synchronisiert, wobei bereits vorhandene, identische Dateien nicht kopiert werden:

#!/bin/bash
mv backup.3 backup.tmp
mv backup.2 backup.3
mv backup.1 backup.2
mv backup.0 backup.1
mv backup.tmp backup.0
cp -al backup.1/. backup.0
rsync -a --delete source_directory/ backup.0/ 

Auf diese Weise werden die Daten nur einmal vollständig kopiert, während für die jeweiligen Versionen nur die Änderungen hinzu kommen. Trotzdem wird immer ein komplettes Verzeichnis angeboten.
Achtung: Bitte in den Backups nichts verändern: Sie sollten immer nur mit ReadOnly-Rechten bereit gestellt werden!!!

Falls der Ziel-Rechner SSH auf einen anderen Port hören lässt, kann dieses dem rsync implizit angegeben werden. Beispiel: Der Zielrechner "remote_host" empfängt ssh-Daten auf Port 12345/tcp. Dann lautet die Letzte Zeile des obigen Skrips:

rsync -a --rsh='ssh -p12345' --delete source_directory/ remote_host:/backup.0/

Besonderheit Windows

Während den meisten Personen zuzutrauen ist, dass sie sich in einer Hierarchischen Struktur die benötigten Daten heraus suchen, bietet Windows die "Vorherigen Versionen" im Kontextmenü des Explorers an. Diese können genauso erzeugt werden, wie die "backup.n" Verzeichnisse oben, doch verlangt Windows, dass die Namen der Snapshots nach einer festen Vorschrift gebildet werden, sonst werden sie von Windows nicht erkannt.
Ein gültiges Format ist: "@GMT-<Date>-<Time>", als Beispiel: @GMT-2016.11.10-14.03.18.
Ein solcher Name muss zur Entstehungszeit des Snapshots erzeugt werden, weshalb unter Linux der Befehl "date" aufgrund seiner flexiblem "Format"-Syntax hierfür hervorragend geeignet ist. Ein passender Verzeichnisname ist somit mit diesem Befehl zu erreichen (Achtung: Der date-Befehl steht in Backticks!!)

mkdir `date +@GMT-%Y.%m.%d-%H.%M.%S`

Das Skript von oben kann damnach do verändert werden:

#!/bin/bash
NEWDIR=`date +@GMT-%Y.%m.%d-%H.%M.%S`
LASTDIR=`ls -td @*|head -1`
OLDESTDIR=`ls -tdr @*|head -1`

# rm -rf $OLDESTDIR
cp -al $LASTDIR/. $NEWDIR
rsync -a --delete source_directory/ $NEWDIR/

Wie immer: Ich gebe keine Garantie!!! Diese Skripten sollen nur Anregungen für eigene Entwürfe sein,  das Ausführen der Skripten kann unter Umständen (falsche Berechtigungen, ungültige Dateinamen etc.) auch zu Datenverlusten führen! Also bitte erst in kleinem Rahmen testen!