ZFS offsite Backup auf eine externe Festplatte

Zu einem persönlichen Daten-GAU ist es bestimmt bei jedem schon einmal gekommen. In meinen frühen Jahren musste ich zweimal Datenverluste durch kaputte Festplatten verkraften. Danach folgten sporadische Kopien auf externe Festplatten, mal hier und mal dort ein Backup. Eine unkoordinierte Sammlung an externen Festplatten, gebrannten CDs und DVDs entstand. Zehn Jahre später gab es erste Fehler beim Lesen gebrannter CDs, außerdem wusste ich auch nicht genau was sich wo genau befand. Seit 2015 betreibe ich nun einen kleinen Heimserver mit FreeNAS, den meine Rechner als Zielmedium für ihr automatisiertes Backup nutzen. Außerdem lagern dort meine restlichen Daten. Wenn eine Platte ausfällt ist noch alles im Lot dank des RaidZ2 aber was ist, wenn der Blitz einschlägt, das Haus brennt, jemand beschließt meinen kleinen Server einfach mitzunehmen oder ich einen unsinnigen Befehl auf der Kommandozeile eintippe? Richtig, dann ist alles weg. 

Trotz, dass ich davor tatsächlich panische Angst habe und mir diese Unzulänglichkeit seit Inbetriebnahme der FreeNAS Box bewusst ist, fehlte es bisher an einem richtigen Backup. Warum? Weil der Weg zu einem richtigen Backup doch schon recht steinig ist, wenn man nur über Halbwissen verfügt.

Mittlerweile liegt eine Kopie meiner Daten ein paar Kilometer weit weg an einem vertrauensvollen Ort, ich schlafe ruhiger und mein Halbwissen zum Thema ZFS hat sich zumindest ein klein wenig erweitert. Vielleicht nützt dieses Wissen dem ein oder anderen etwas. Wenn nicht, so hab ich mit der folgenden Anleitung immernoch eine Notiz wie das Backup im Falle des Falles einzuspielen ist.

 

Anforderungen

Folgende Kriterien waren für mich entscheidend:

  • offsite Backup – die Daten sollen an einem physisch anderen Ort aufbewahrt werden
  • keine Cloud – ich möchte keinen (kommerziellen) Dritten dazwischen schalten; keine Terrabytes über das Internet morsen
  • schneller Zugriff auf einzelne Dateien im Notfall ohne spezielle Hardware aufsetzen zu müssen

Folgende Kriterien sind für mich nicht entscheidend:

  • 24/7 Aktualität des Backups – es geht hier nur um meine privaten Daten
  • 24/7 Zugang zum Backup

 

Backup-Strategie

Es steht ja schon im Titel – es ist eine Lösung mit externer Festplatte geworden. Diese wird per USB an die FreeNAS Box angeschlossen, das Update-Skript gestartet und anschließend wird die Platte an einen vertrauensvollen Ort transferiert.

Das Ganze findet im rotierenden System statt. Wenn also eine Platte zum vertrauenvollen Ort wandert, wird gleichzeitig eine von dort wieder mitgenommen und wiederum mit dem aktuellen Datenstand versehen. Der Plan ist dies monatlich durchzuführen.

Da die Daten auf der FreeNAS Box schon in einem ZSF Pool liegen bietet es sich natürlich an diesen mit zfs send | zsf receive auf die USB-Platte zu spiegeln. Für alle Eventualitäten hebe ich noch die letzen 3 Snapshots auf.

 

Umsetzung

1. Pool anlegen

Auf der USB-Platte muss natürlich erstmal ein ZSF Pool angelegt werden. Die Platte wird dazu an das FreeNAS angeschlossen und anschließend in der Konsole ein dmesg ausgeführt. Die letzten Zeilen der dmesg Ausgabe könnten zum Beispiel so aussehen:

umass1 on uhub2
umass1: <Western Digital Elements 25A2, class 0/0, rev 2.10/10.14, addr 5> on usbus0
umass1:  SCSI over Bulk-Only; quirks = 0xc101
umass1:8:1: Attached to scbus8
da1 at umass-sim1 bus 1 scbus8 target 0 lun 0
da1: <WD Elements 25A2 1014> Fixed Direct Access SPC-4 SCSI device
da1: Serial Number 575842314141364832304143
da1: 40.000MB/s transfers
da1: 1907697MB (3906963456 512 byte sectors)
da1: quirks=0x2<NO_6_BYTE>

Das da1 ist die gesuchte Information (USB-Speicher werden in FreeBSD mit da0, da1, da1, ... bezeichnet), die Platte können wir nun nämlich über /dev/da1 ansprechen. Mit dem folgenden Befehl wird die ganze Platte für den ZFS Pool verwendet, wir nennen ihn backup.
Achtung: Seid euch bitte 100% sicher, dass /dev/da1 eure USB-Platte anspricht und keine andere, sonst braucht ihr kein Backup mehr ;-)

zpool create -f -O compression=lz4 -O atime=off -O casesensitivity=insensitive -O normalization=formD backup /dev/da1

Wenn keine Fehlermeldung aufgetaucht ist können wir nun den Pool auswerfen, unser Backup-Script wird ihn später wieder einbinden.

zpool export backup

 

2. Backup Skript

Meine Daten liegen alle in dem Pool data. Darin habe ich mehrere Datasets, wovon im folgenden Beispiel nur media und timemachine in das Backup sollen.

FreeNAS: Storage

Das folgende Skript wird zum Beispiel als backup.sh in einem Verzeichnis auf dem FreeNAS gespeichert. Im oberen Bereich erfolgen die individuellen Anpassungen (siehe Kommentare im Skript).

#!/bin/bash

# Pool mit den zu sichernden Daten
MASTERPOOL="data"

# Backup-Pool
BACKUPPOOL="backup"

# Datasets, die in das Backup sollen
DATASETS=("media" "timemachine")

# Anzahl der zu behaltenden letzten Snapshots, mindestens 1
KEEPOLD=3

# Praefix fuer Snapshot-Namen
PREFIX="auto"

# -------------- ab hier nichts aendern ---------------

zpool import $BACKUPPOOL

KEEPOLD=$(($KEEPOLD + 1))

for DATASET in ${DATASETS[@]}
do
    # Namen des aktuellsten Snapshots aus dem Backup holen
	recentBSnap=$(zfs list -rt snap -H -o name "${BACKUPPOOL}/${DATASET}" | grep "@${PREFIX}-" | tail -1 | cut -d@ -f2)
	if [ -z "$recentBSnap" ] 
		then
			dialog --title "Kein Snapshot gefunden" --yesno "Es existiert kein Backup-Snapshot in ${BACKUPPOOL}/${DATASET}. Soll ein neues Backup angelegt werden? (Vorhandene Daten in ${BACKUPPOOL}/${DATASET} werden ueberschrieben.)" 15 60
			ANTWORT=${?}
			if [ "$ANTWORT" -eq "0" ]
				then
					# Backup initialisieren
					NEWSNAP="${MASTERPOOL}/${DATASET}@${PREFIX}-$(date '+%Y%m%d-%H%M%S')"
					zfs snapshot -r $NEWSNAP
					zfs send -v $NEWSNAP | zfs recv -F "${BACKUPPOOL}/${DATASET}"
			fi
			continue
	fi
	
	# Check ob der korrespondierende Snapshot im Master-Pool existiert
	origBSnap=$(zfs list -rt snap -H -o name "${MASTERPOOL}/${DATASET}" | grep $recentBSnap | cut -d@ -f2)
	if [ "$recentBSnap" != "$origBSnap" ]
		then
			echo "Fehler: Zum letzten Backup-Spanshot ${recentBSnap} existiert im Master-Pool kein zugehoeriger Snapshot."
			continue
	fi
	
	echo "aktuellster Snapshot im Backup: ${BACKUPPOOL}/${DATASET}@${recentBSnap}"
	
	# Name fuer neuen Snapshot
	NEWSNAP="${MASTERPOOL}/${DATASET}@${PREFIX}-$(date '+%Y%m%d-%H%M%S')"
	# neuen Snapshot anlegen
	zfs snapshot -r $NEWSNAP
	echo "neuen Snapshot angelegt: ${NEWSNAP}"
	
	# neuen Snapshot senden
	zfs send -v -i $recentBSnap $NEWSNAP | zfs recv "${BACKUPPOOL}/${DATASET}"
	
	# alte Snapshots loeschen
	zfs list -rt snap -H -o name "${BACKUPPOOL}/${DATASET}" | grep "@${PREFIX}-" | tail -r | tail +$KEEPOLD | xargs -n 1 zfs destroy -r
	zfs list -rt snap -H -o name "${MASTERPOOL}/${DATASET}" | grep "@${PREFIX}-" | tail -r | tail +$KEEPOLD | xargs -n 1 zfs destroy -r
done

zpool export $BACKUPPOOL

 

3. Backup durchführen

So ein Backup auf eine USB-Platte kann schon ein ganzes Weilchen dauern. Damit die Skript-Ausführung nicht abbricht falls zum Beispiel die Terminal-App aus Versehen geschloßen wird oder die SSH-Verbindung zu FreeNAS Schluckauf bekommt sollte das ganze in einer virtuellen Konsole ausgeführt werden. Dazu eignet sich zum Beispiel das Programm tmux. Dieses wird auf der Konsole einfach mit dem Befehl tmux gestartet und es öffnet sich eine virtuellen Konsole. Um diese zu verlassen ohne sie zu schließen wird einfach [Strg]+[B] und anschließend [D] gedrückt (auch wenn gerade das Backu-Skript läuft). Zum Zurückkehren wird der Befehl tmux attach genutzt (Achtung: Wenn ihr als root tmux startet, müsst ihr natürlich wieder als root die virtuelle Sitzung aufnehmen).

Es wird in der virtuellen Konsole mit cd in das Verzeichnis mit dem Backup Script gewechselt und anschließend das Skript gestartet:

./backup.sh

Was passiert jetzt? Zunächst wird der backup Pool eingebunden. Anschließend wird das eigentliche Backup durchgeführt. Dabei erscheint beim erstmaligen Durchlauf für jedes Dataset ein Dialog, welcher fragt ob ein neues Backup angelegt werden soll. Hier ist natürlich ja auszuwählen. Solltet dieser Dialog irgendwann später nochmal auftauchen so ist etwas schief gegangen.

Das Skript erzeugt nun automatisch mit jedem Durchlauf einen Snapshot für jedes angegebene Dataset und benennt diesen mit dem aktuellen Datum, zum Beispiel: data/timemachine@auto-20180218-232209. Dieser Snapshot wird anschließend inkrementell auf die USB-Platte gesendet. Beim ersten Durchgang dauert dies je nach Größe der Daten recht lange. Bei weiteren Durchläufen werden nur noch die Änderungen übertragen. Anschließend werden sowohl auf dem FreeNAS als auch auf der USB-Platte alte Snapshots gelöscht, bis auf die drei letzten (kann mit KEEPOLD eingestellt werden).

Zum Abschluss exportiert das Skript noch den backup Pool – die USB-Platte wird ausgeworfen. Wenn keine Fehlermeldungen aufgetaucht sind kann die Platte nun wieder abgestöpselt werden.

 

4. Backup einspielen

Nehmen wir an der Nachbar über mir hat einen Wasserschaden und mein FreeNAS ist baden gegangen. Was nun? Wie komme ich wieder an meine Daten? Dieser Schritt sollte unbedingt getestet werden, bevor man sich zufrieden zurücklehnt und in Sicherheit wägt. 

4.1 Komplettes Backup in einen neuen Pool einspielen

Für diesen Fall muss selbstverständlich ein Rechner mit einem ZFS unterstützenden Betriebssystem bereit stehen. Wir gehen einfach mal wieder von einer FreeNAS Box aus. Auf diesem Rechner wird ein neuer Pool angelegt (z.B. in der FreeNAS Weboberfläche) mit dem Namen newpool. Anschließend wird die USB-Platte mit dem Backup angeschlossen und eingebunden.

zpool import backup

Mit dem obigen Skript haben wir nur einzelne Datasets gesichert, diese müssen jetzt auch einzeln wiederhergestellt werden. Zunächst schauen wir, was denn eigentlich da ist.

zfs list -rt snap -o name,creation backup

Dieser Befehl erzeugt eine Ausgabe wie zum Beispiel:

NAME                                        CREATION
backup/media@auto-20180219-124435           Mon Feb 19 12:44 2018
backup/media@auto-20180219-130558           Mon Feb 19 13:05 2018
backup/timemachine@auto-20180219-124435     Mon Feb 19 12:44 2018
backup/timemachine@auto-20180219-130558     Mon Feb 19 13:05 2018

Um nun den letzten Snapshot vom Dataset media einzuspielen ist folgendes notwendig:

zfs send -R backup/media@auto-20180219-130558 | zfs recv -vF newpool/media

Jetzt sollten die eingespielten Daten noch geprüft werden:

zpool scrub newpool

Zum Schluss wird die USB-Platte ausgehangen:

zpool export backup

 

4.2 Wie komme ich ganz schnell an DIE eine Datei?

Im Falle des Daten-GAUs ist möglicherweise kein Gerät vorhanden, um die ganzen Datasets wieder einzuspielen, trotzdem muss man unter Umständen an bestimmte Daten herankommen. Da mit zfs send | zfs receive ein vollständiges Dateisystem auf die USB-Platte geschrieben wurde, kann diese auch an jedem ZFS unterstützenden Rechner gelesen werden. 

Ich habe das Ganze einmal an meinem Mac ausprobiert. Dazu muss auf dem Mac OpenZFS on OSX installiert werden. Nun kann die USB-Platte an den Mac angeschlossen werden. Etwaige Angebote von OSX die Platte zu initialisieren oder ähnliches sind strengstens abzulehnen.

OSX nimm die Finger weg!

Der backup Pool auf der USB-Platte wird nun als readonly nach /Volumes/backup gemountet. Da hierfür root Rechte notwendig sind, wird sudo benutzt, es verlangt anschließend das Nutzer-Passwort.

sudo zpool import -o readonly=on -o altroot=/Volumes/backup backup

Nun sollten die Datasets nach einige Sekunden im Finder auftauchen, Dateien können jetzt einfach auf den Mac kopiert werden. Zum Abschluss muss der Pool jedoch unbedingt wieder mit zpool export ausgeworfen werden.

zpool export backup

 

Anmerkungen

Wie bereits eingehend erwähnt: Die vorgestellte Backup Lösung ist meine eigene Variante für meine privaten Daten, von deren Existenz nicht das Weltgeschehen abhängt. Wenn ihr ähnliches vor habt, nutzt diese Anleitung als Hilfestellung aber informiert euch vorher ausführlich über ZFS, zum Beispiel dort:

Lest euch das obige Backup-Skript durch und versucht es nachzuvollziehen – nutzt es nicht blind, schreibt vielleicht sogar euer eigenes! Lest euch auf der Konsole eingegebene Befehle nocheinmal genau durch, bevor ihr auf Enter drückt. Testet euer Backup erstmal mit Testdaten. Probiert auch unbedingt Schritt 4 aus. Überprüft, welche Snapshots erstellt werden, zum Beispiel mit:

zfs list -rt snap -o name,creation

Ich wünsche euch viel Erfolg auf dem Weg zu eurem Backup!

  10.04.18 um 19:20 Uhr
  freenas, zfs
nächster Artikel:
Aprilbild 2018
auch lesen:
vorheriger Artikel:
Märzbild(er) 2018
auch lesen:

Kommentare

Christian
schrieb am 20.07.18 um 10:26 Uhr:

Hallo Jörg,
durch Zufall bin ich beim Recherchieren auf deinen Beitrag gestoßen. Genau nach dieser Lösung suche ich derzeit und werde deine Anleitung als roten Faden nehmen.
Vielen Dank für die Dokumentation.
Gruß
Christian

Thomas
schrieb am 10.10.18 um 20:48 Uhr:

Spitzen Anleitung. Daumen hoch.

Max
schrieb am 30.04.19 um 15:03 Uhr:

Nice, Danke!

Stefan
schrieb am 18.08.19 um 18:27 Uhr:

Besten Dank für die ausführliche Anleitung. Sie hat mir die Migration meines zfs-Pools sehr erleichtert.

Markus
schrieb am 19.08.19 um 22:11 Uhr:

Kurze Anmerkung:
Wenn man KEEPOLD=3 einstellt, also auf dem Quellsystem drei Snapshots vorgehalten werden, man aber bspw. mit einem Rotationssystem aus sieben externen Zielplatten arbeitet, dann hat man ein Problem. Man müsste dann, käme man zum zweiten Mal bei der fünften Platte an, wieder ein Vollbackup erstellen (wenn ich mich nicht verzählt habe). Um sicher zu gehen empfiehlt es sich KEEPOLD auf die Anzahl der externen Zielplatten +1 zu stellen.

Thomas
schrieb am 03.09.19 um 13:57 Uhr:

Tolle Anleitung! Sehr hilfreich und die Gedanken sind prima erklärt. So etwas habe ich gebraucht.

Matthias
schrieb am 07.11.19 um 14:09 Uhr:

Ich hab womöglich ein Verständnisproblem: Ich möchte ein Archiv als Backup aufbauen. Daten welche auf normlane Pools liegen, sollen mittels snapshots und send/receive in eine Art Archiv gesichert werden, also einen zweiten Pool welcher dann nur lesbar sein soll. Erfüllt das Skript diese Bedingungen?

der B.
schrieb am 13.11.19 um 22:56 Uhr:

@Matthias: Ja, das kann das Skript. Wenn der Backup-Pool immer verfügbar sein soll, musst du nur den Export weg lassen. Die Lese- und Schreibrechte setzt du über die Benutzerrechte, das macht das Skript nicht ;)

Florian
schrieb am 15.11.19 um 9:11 Uhr:

Hallo Jörg, danke für den Post. Da auch ich mein ubuntu-zfs nur Hobby-mäßig zu privaten Zwecken betreibe hat mich der Artikel sehr weitergebracht, Danke für den Erkenntnisgewinn! :)
*FRAGEN* zu Plattenkapazität:
(1) Da es sich bei dem backup-vdev quasi um ein RAID0 handelt, steht der komplette Platz der Backup-Platte zur Verfügung, richtig?
(2) In deinem Beispiel kommst du auf ca. 1400 GiB netto Nutzdaten (media 790 GiB, timemachine 610 GiB). Würde also eine 2TB reichen, obwohl in deinem FreeNAS der verfügbare Speicherplatz deutlich größer wäre?

der B.
schrieb am 18.11.19 um 17:08 Uhr:

@Florian: Danke für das Lob :)
(1) In meinem Fall ist das Backup-Ziel nur eine externe Festplatte deren voller Platz zur Verfügung steht, ein RAID0 ist das aber nicht. Worauf letztendlich der Backup-Pool erstellt wird ist egal, es kann auch auf einem RAID-Verbund sein.
(2) Ja 2 TB reichen, solange die zu sichernden Daten nicht viel größer werden.

Raphael
schrieb am 15.12.19 um 17:16 Uhr:

Super Artikel. Leider funktioniert das nur mit unverschlüsselten Pools. Gibt's auch eine automatisierte Möglichkeit, verschlüsselte Pools auf eine externe Festplatte zu sichern?

der B.
schrieb am 15.12.19 um 20:13 Uhr:

@Raphael: Damit habe ich mich bisher noch nicht beschäftigt und kann somit leider nicht sagen wie so eine Lösung funktioniert. Aber automatisieren lässt sich alles ;)

Niklas
schrieb am 29.12.19 um 19:41 Uhr:

Danke für dieses großartige Skript. Es erfüllt seit einigen Monaten unaufällig seinen Dienst für mich. Ich bin nun dabei, dieses nach meinem persönlichen Geschmack "umzubauen", sodass im ersten Schritt die alle Snapshots im Masterpool erstellt, im zweiten Schritt die erstellten Snapshots gesendet und im dritten Schritten dann alle "alten" Snapshots gemäß "KEEPOLD"-Variable gelöscht werden.

Beim Umbauen des dritten Schritts kam mir dann ein Gedanke: Beim Initialisieren wird ein Voll-Backup erstellt und gesendet. Alle darauf folgenden Snapshots werden nur noch inkrementell gesendet und bis auf die letzten Backups (KEEPOLD) gelöscht. Wird damit dann nicht auch früher oder später das initiale Voll-Backup gelöscht, auf dem die Inkremente beruhen? Wenn dem so wäre, lägen nach mehreren Durchgängen nur noch unvollständige Backups vor. Bitte bring mir da etwas Licht ins Dunkel.

Philip Scheiwiller
schrieb am 30.12.19 um 20:14 Uhr:

Hallo Jörg,
auch von meiner Seite aus vielen Dank! Hat bei mir soweit alles reibungslos funktioniert.
Beim überprüfen auf dem Mac mittels OpenZFS ist mir aufgefallen, dass bei einem Dataset nicht zugegriffen werden kann, resp. die Berechtigung fehlen. Ich denke, dass die Berechtigungen vom freenas übernommen wurden und mit dem Mac-Benutzer ja nicht übereinstimmen. Die anderen Datasets funktionieren, da dort die Berechtigung für "nobody" gelten.
Habe mich auch mal etwas schlau gemacht und bin zu keinem Ergebnis gekommen, wie der Zugriff ermöglicht werden kann. Hast du allenfalls einen Anhaltspunkt oder einen Tipp dafür? Mir gehts darum, dass ich unabhängig vom OS auf die Daten zugreifen könnte (wenn was schief laufen sollte).

Danke & Gruß Philip

der B.
schrieb am 31.12.19 um 0:43 Uhr:

Danke für eure Kommentare! Es freut mich, dass das Skript genutzt und angepasst wird :-)

@Niklas: Das Voll-Backup wird nicht gelöscht, nur die Möglichkeit im Backuppool zu dem Zeitpunkt des Voll-Backups (nennen wir es snap1) zurück zu springen. Die ZFS-Magie löscht nur das, was wir tatsächlich löschen wollen.
Aber Achtung: Diese Backup-Variante funktioniert wie ein Mirror in Richtung Originalpool => Backuppool. Nehmen wir an du hast in deinem Originalpool die Datei abc.xyz angelegt und erstellst anschließend den Snapshot snap1. Dieser wird dann mit obigem Skript in den Backuppool gesichert. Irgendwann löschst du die Datei abc.xyz und erstellst danach den Snapshot snap2, welcher wiederum ins Backup gezogen wird. Solange im Backuppool noch snap1 vorhanden ist, kannst du daraus die Datei abc.xyz wieder herstellen. Löschst du jedoch snap1, so ist nur noch ein Rollback zu snap2 möglich, darin war im Originalpool die Datei abc.xyz jedoch nicht mehr vorhanden, also fehlt sie jetzt auch im Backup.
Wenn du also jederzeit auf alle deine gelöschten Dateien zurückgreifen willst, so darf im Backuppool nichts gelöscht werden.

@Philip Scheiwiller: Ja es werden die Berechtigungen von FreeNAS übernommen, wenn diese nicht mit dem Mac-Benutzer übereinstimmen kommst du nur mit root-Rechten weiter. Die schnelle Variante wäre in der Konsole mit su zum Root-Nutzer zu wechseln und dann von da aus die Daten zu kopieren. Anschließend kannst du als root mit dem Befehl chown einen neuen Benutzer zuweisen.
Eine andere (aus Sicherheitsgründen nicht zu empfehlende) Variante wäre es den Finder als root zu starten, dafür hilft dir deine Suchmaschine des Vertrauens weiter.

Björn
schrieb am 03.02.20 um 17:05 Uhr:

Hallo,

Ich bin auch gerade dabei mir dein Script etwas anzupassen (verschlüsselte USB-HDD, unrekursive backups etc) aber verstehe nicht wie genau das bei dir funktioniert. Wenn ich das richtig sehe wird von jedem dataset ein rekursiver Snapshot erstellt und auch sowohl für die Erkennung des letztes gebackupten Snapshots wie auch zum Löschen alter Snapshots eine rekursive Liste erstellt.
Wie läuft das denn z.B. beim Löschen? Wenn ich das richtig sehe würde das Script bei mir falsche Snapshots löschen:

Das wären z.B. meine Snapshots vom "HDDpool/HDD-Share"

# zfs list -rt snap -H -o name "HDDpool/HDD-Share" | grep "@auto-" | tail -r
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200203.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200202.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200201.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200131.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200130.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200129.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200128.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200203.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200202.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200201.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200131.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200130.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200129.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200128.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200203.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200202.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200201.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200131.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200130.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200129.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200128.0300-1w
HDDpool/HDD-Share@auto-20200203.0300-1w
HDDpool/HDD-Share@auto-20200202.0300-1w
HDDpool/HDD-Share@auto-20200201.0300-1w
HDDpool/HDD-Share@auto-20200131.0300-1w
HDDpool/HDD-Share@auto-20200130.0300-1w
HDDpool/HDD-Share@auto-20200129.0300-1w
HDDpool/HDD-Share@auto-20200128.0300-1w

Und dein Löschbefehl gibt das weiter:

# zfs list -rt snap -H -o name "HDDpool/HDD-Share" | grep "@auto-" | tail -r | tail +2
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200202.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200201.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200131.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200130.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200129.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200128.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200203.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200202.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200201.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200131.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200130.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200129.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200128.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200203.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200202.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200201.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200131.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200130.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200129.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200128.0300-1w
HDDpool/HDD-Share@auto-20200203.0300-1w
HDDpool/HDD-Share@auto-20200202.0300-1w
HDDpool/HDD-Share@auto-20200201.0300-1w
HDDpool/HDD-Share@auto-20200131.0300-1w
HDDpool/HDD-Share@auto-20200130.0300-1w
HDDpool/HDD-Share@auto-20200129.0300-1w
HDDpool/HDD-Share@auto-20200128.0300-1w

Da würde dann doch alles an Snapshots außer "HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200203.0300-1w" gelöscht werden obwohl eigentlich alles mit dem "@auto-20200203.0300-1w" behalten werden sollte. Die richtige Löschliste wäre dann doch eigentlich folnde:
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200202.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200201.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200131.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200130.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200129.0300-1w
HDDpool/HDD-Share/LowSec/Stuff_HDD@auto-20200128.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200202.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200201.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200131.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200130.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200129.0300-1w
HDDpool/HDD-Share/LowSec/Series@auto-20200128.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200202.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200201.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200131.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200130.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200129.0300-1w
HDDpool/HDD-Share/LowSec@auto-20200128.0300-1w
HDDpool/HDD-Share@auto-20200202.0300-1w
HDDpool/HDD-Share@auto-20200201.0300-1w
HDDpool/HDD-Share@auto-20200131.0300-1w
HDDpool/HDD-Share@auto-20200130.0300-1w
HDDpool/HDD-Share@auto-20200129.0300-1w
HDDpool/HDD-Share@auto-20200128.0300-1w

Und dann stellt sich mir noch die Frage ob es reicht da einfach nur mit "zfs send -v $NEWSNAP | zfs recv -F "${BACKUPPOOL}/${DATASET}"" das Eltern-Dataset zu senden. Wird werden da dann automatisch alle Unter-Dataset mitgesendet oder müsste man die alle einzeln senden? Das "zfs snapshot -r $NEWSNAP" erstellt ja für jeden Unter-Datensatz einen eigenen Snapshot.

Christian
schrieb am 18.06.20 um 22:25 Uhr:

Hallo,

ich habe aktuell ein sehr aktues Problem: Mein Pool ist an irgendeiner Stelle corrupted, was ständig zu einem Reboot des Servers führt. Ich kann den Fehler nicht finden. Wenn ich den Pool jedoch readonly mounte läuft der Server stabil, sodass ich Daten sichern könnte. Dein Script mosert nun zurecht, dass es kein Snapshot erstellen kann, da ja readonly. Ginge es irgendwie den Snapshot quasi in-the-fly auf die backupplatte zu erstellen?

Ich wäre über Hilfe sehr dankbar.

Gruß Christian

der B.
schrieb am 18.06.20 um 22:52 Uhr:

@Christian: Soweit ich weiß kann man Snapshots nur direkt auf dem Dateisystem bzw. Volume erstellen, von dem man es erstellt.
Du kannst jetzt im readonly nur den letzten noch vorhandenen Snapshot per zfs send auf deine Backupplatte schieben. Dann fehlen aber halt die Änderungen seit dem letzten Snapshot. Für solche Fälle hab ich automatische tägliche Snapshots laufen, die nach einer Woche wieder gelöscht werden.
Aber frag mal in einem Forum mit ZFS-Experten nach wie du noch an deine Daten ran kommen könntest, ich bin kein Guru auf dem Gebiet ;-)

janwels89
schrieb am 02.07.20 um 19:09 Uhr:

Hallo, Ich habe diseses Skript gefunden und benutze es auf meinen Debian Server mit OpenMediaVault V4. Leider gibt es "tail -r" nicht auf linux-systemen. Das kann man aber einfach mit "tac" ersetzen.

Ich habe den code mal auf github gepostet, damit ihr euch beteiligen könnt, wenn ihr wollt. Ich habe eine Copyright-Hinweiß für Jörg eingefügt. Ich hoffe das geht in Ordnung?

https://github.com/janwels89/backup-zfs-bash

der B.
schrieb am 07.07.20 um 22:16 Uhr:

@janwels89: Das passt :-)

Marcin
schrieb am 10.07.20 um 10:04 Uhr:

Hallo,

ich danke Dir für den script.
Ich habe ein folgendes problem, ich habe ein dataset mit Leerzeichen im name und das kann dieser Skript nicht beherrschen. Hast du eine idee wie ich es losen kann?

Ein Beispiel:
Dataset name:"Test Data"
Der Skript versucht aus "Test Data" zwei unterschiedliche datasets zu erstellen, "Test" und "Data"

Vielen Dank
Marcin

der B.
schrieb am 10.07.20 um 21:32 Uhr:

@Marcin: Hast du es schon mal versucht das Leerzeichen zu escapen?
"Test\ Data"
Der bessere Weg wäre allerdings auf Leerzeichen in Dataset-Bezeichnungen zu verzichten.

Marcin
schrieb am 13.07.20 um 8:36 Uhr:

@der B.: Ja ich habe es auch schon versucht.
Fehlermeldung lautet: cannot open 'backup/Test\': invalid character '\' in name.

Die Lösung ist aber einfach, ich habe Dataset "Test Data" auf "Test_Data" umbenannt mit zfs rename Befehl.

DFFVB
schrieb am 29.10.20 um 10:45 Uhr:

Das ist ein großartiger Beitrag, der in der Evaluierung von verschiedenen NAS Lösungen, einen wichtigen Haken bei FreeNAS machen lässt, nämlich "Cold BackUp für NAS". Du erklärst DAU-gerecht und nimmst etwas Berührungsangst vor ZFS. Sehr schön, wie Du auch auf die Wiederherstellung eingehst, denn das ist der zweite Haken. Bspw. hat OMV auch eien BackUp Funktion, wer nach Wiederherstellung sucht, findet nüscht, bzw. wird dann extremes Wissen gefordert (no hate gegen OMV, habe Volker auch schon gespendet).

Anyway: In den Kommentaren kam ja schon die Kiste mit den verschiedenen Benutzern. Vlt könntest Du den Beitrag noch darum ergänzen?

Daniel
schrieb am 12.01.21 um 18:00 Uhr:

Super Anleitung, vielen Dank dafür. Ich versuche gerade das Script zu verstehen, und habe da ein paar Fragen, die mir die Doku nicht beantworten konnte. Über eine Antwort würde ich mich freuen:
- Wieso ist der Parameter -F bei zfs recv notwendig, bzw. was macht dieser? Laut Doku: "Force a rollback of the file system to the most recent snapshot before performing the receive operation." Nach meinem Verständnnis bezieht sich das auf das empfangende DataSet, nur warum muss das sein? Sollte das nicht auf einem konsistenten Stand sein?
- Die Parameter zum Anlegen des Backup-Pools sind mir nicht klar: Warum werden diese auf "casesensitivity=insensitive" und "normalization=formD" gesetzt? Intuitiv hätte ich diese auf sensitive und none gesetzt.
Danke, Daniel

Daniel
schrieb am 16.01.21 um 12:25 Uhr:

Ok, ich habe die Antworten gefunden, zumindest teilweise:
Die Parameter zum Anlegen scheinen für MacOS zu gelten, bei mir (Linux/FreeBSD) habe ich diese anders gesetzt. Der Parameter -F ist mir noch nicht klar.
In der Praxis werde ich wohl aber auf https://github.com/jimsalterjrs/sanoid/wiki/Syncoid setzen.

der B.
schrieb am 16.01.21 um 13:22 Uhr:

@Daniel: zfs receive -F wird immer nur dann ausgeführt, wenn auf dem BACKUPPOOL kein passender Snapshot gefunden wurde und ein neues Backup in dem Pool initialisiert werden soll (nach der Sicherheitsabfrage). Durch die Option -F werden dann im BACKUPPOOL alle Snapshots entfernt, die nicht auf der sendenen Seite vorhanden sind. Das ist nur für den Fall relevant, wo schon mal in dem BACKUPPOOL ein gleichnamiges Dataset exisitert, was aber nicht mehr zu den vorhandenen Snapshots auf der sendenden Seite passt.

Daniel
schrieb am 18.01.21 um 16:50 Uhr:

@der B. Danke für die Erläuterung; jetzt ist es klar :D
Noch eine etwas OT-Frage: Hast Du Erfahrungen mit Parametern zur Pool-Erzeugung. Ich würde bis jetzt (für meine Backup-Platte) soetwas in der Art vorsehen:
zpool create -f -o ashift=12 -O compression=lz4 -O mountpoint=none \
-O normalization=formD <pool> /dev/xxx
Gibt es hierzu "best practices", oder Erfahrungen?

der B.
schrieb am 18.01.21 um 21:06 Uhr:

@Daniel: Was die Parameter zur Pool-Erzeugung angeht bin ich momentan raus, dafür mach ich zu wenig ZFS Krempel ;-)

Kommentar verfassen





optional, wird nicht veröffentlicht

optional

Bitte rückwärts eingeben!