Obwohl tar
hat einen inkrementellen Modus, es gibt ein paar umfassendere Tools, um die Arbeit zu erledigen:
- Duplizität
- Duplikate
Sie unterstützen nicht nur inkrementelle Sicherungen, es ist auch einfach, einen Zeitplan zu konfigurieren, nach dem eine vollständige Sicherung durchgeführt werden muss. Zum Beispiel in duplicity
:duplicity --full-if-older-than 1M
stellt sicher, dass eine vollständige Sicherung ausgeführt wurde. Sie unterstützen auch das Zurückgehen in der Zeit zu einer bestimmten Datei, mit einfachem tar müssen Sie alle inkrementellen Dateien durchgehen, bis Sie eine gefunden haben, die die richtige Datei enthält.
Darüber hinaus unterstützen sie die Verschlüsselung und das Hochladen auf eine Vielzahl von Backends (wie sftp, Blob-Speicher usw.). Wenn Sie verschlüsseln, vergessen Sie natürlich nicht, eine gute Sicherung Ihrer Schlüssel auf einer sekundären Sicherung zu erstellen!
Ein weiterer wichtiger Aspekt ist, dass Sie die Integrität Ihrer Sicherungen überprüfen können, um sicherzustellen, dass Sie sie wiederherstellen können, z. B. mit duplicity verify
.
Ich würde negativ zu einer Git-basierten Backup-Strategie raten. Große Wiederherstellungen nehmen viel Zeit in Anspruch.
Ich habe rsync ausprobiert, aber es scheint nicht in der Lage zu sein, das zu tun, was ich will, oder wahrscheinlicher, ich weiß nicht, wie ich das machen soll.
Ich weiß, dass ich wahrscheinlich ein Skript erstellen könnte, das einen Diff ausführt und dann die zu sichernden Dateien basierend auf dem Ergebnis auswählt (oder effizienter, einfach eine Prüfsumme erhält und vergleicht), aber ich möchte wissen, ob es ein Dienstprogramm gibt, das dies tun kann a etwas einfacher :)
rsync
ist genau das programm, das auf basis eines diffs kopiert. Standardmäßig kopiert es nur, wenn es einen Unterschied in der Zeit oder Größe der letzten Änderung gibt, aber es kann sogar anhand der Prüfsumme mit -c
vergleichen .
Das Problem dabei ist, dass Sie tar
sind 'ing die Backups. Dies wird einfacher, wenn Sie das nicht tun. Ich weiß nicht einmal, warum du es tust. Es könnte sinnvoll sein, sie zu komprimieren, aber das tun Sie nicht einmal.
Der Wikipedia-Artikel für inkrementelle Sicherungen enthält ein Beispiel rsync
Befehl, der ungefähr so lautet:
rsync -va \
--link-dest="$dst/2020-02-16--05-10-45--testdir/" \
"$src/testdir/" \
"$dst/2020-02-17--03-24-16--testdir/"
Es werden Dateien aus der vorherigen Sicherung fest verknüpft, wenn sie gegenüber der Quelle unverändert sind. Es gibt auch --copy-dest
wenn Sie stattdessen kopieren möchten (es ist immer noch schneller, wenn $dst
ist eine Fernbedienung oder auf einem schnelleren Laufwerk).
Wenn Sie ein Dateisystem mit Subvolumes wie btrfs verwenden, können Sie vor dem Rsync auch nur einen Snapshot von der vorherigen Sicherung erstellen. Snapshots werden sofort erstellt und nehmen keinen zusätzlichen Speicherplatz ein[1].
btrfs subvolume snapshot \
"$dst/2020-02-16--05-10-45--testdir" \
"$dst/2020-02-17--03-24-16--testdir"
Oder wenn Sie ein Dateisystem verwenden, das Reflinks unterstützt, wie ext4, dann können Sie das auch tun. Reflinks werden erstellt, indem ein neuer Inode erstellt wird, aber auf dieselben Blöcke wie die Quelldatei verwiesen wird, wodurch die COW-Unterstützung implementiert wird. Es ist immer noch schneller als normales Kopieren, da es die Daten nicht liest und schreibt und auch keinen zusätzlichen Speicherplatz beansprucht[1].
cp --reflink -av \
"$dst/2020-02-16--05-10-45--testdir" \
"$dst/2020-02-17--03-24-16--testdir"
Wie auch immer, sobald Sie so etwas getan haben, können Sie einfach ein normales rsync
machen um die Unterschiede zu kopieren:
rsync -va \
"$src/testdir/" \
"$dst/2020-02-17--03-24-16--testdir/"
Vielleicht möchten Sie jedoch --delete
hinzufügen , was dazu führen würde, dass rsync Dateien vom Ziel löscht, die nicht mehr in der Quelle vorhanden sind.
Eine weitere nützliche Option ist -i
oder --itemize-changes
. Es erzeugt eine prägnante, maschinenlesbare Ausgabe, die beschreibt, welche Änderungen rsync vornimmt. Normalerweise füge ich diese Option hinzu und pfeife wie folgt:
rsync -Pai --delete \
"$src/testdir/" \
"$dst/2020-02-17--03-24-16--testdir/" \
|& tee -a "$dst/2020-02-17--03-24-16--testdir.log"
um die Änderungen einfach über grep
aufzuzeichnen fähige Dateien. Die |&
ist, sowohl stdout als auch stderr zu leiten.
Die -P
ist die Abkürzung für --partial
und --progress
. --partial
behält teilweise übertragene Dateien, aber noch wichtiger --progress
meldet den Fortschritt pro Datei.
Vergleich zum Archivieren von Änderungen mit tar
Die obigen Lösungen führen zu Verzeichnissen, die scheinbar alles enthalten. Obwohl dies der Fall ist, würden sie insgesamt für jede Menge/Häufigkeit von Backups ungefähr die gleiche Menge an Speicherplatz belegen wie einfache Tar-Archive mit nur Änderungen. Das liegt an der Funktionsweise von Hardlinks, Reflinks und Snapshots. Die Bandbreitennutzung beim Erstellen der Backups wäre ebenfalls gleich.
Die Vorteile sind:
- Backups lassen sich mit rsync einfach und schneller wiederherstellen, da rsync nur die Unterschiede aus dem Backup übertragen würde.
- Sie sind einfacher zu durchsuchen und bei Bedarf zu ändern.
- Dateilöschungen können natürlich als Fehlen der Datei in neuen Backups kodiert werden. Bei der Verwendung von tar-Archiven müsste man auf Hacks zurückgreifen, etwa um eine Datei zu löschen
foo
, markieren Sie esfoo.DELETED
oder etwas Kompliziertes tun. Ich habe zum Beispiel nie Duplizität verwendet, aber wenn ich mir die Dokumentation ansehe, scheint es, dass es Löschungen codiert, indem es eine leere Datei mit demselben Namen in das neue tar hinzufügt und die ursprüngliche Signatur der Datei in einer separaten .sigtar-Datei enthält. Ich stelle mir vor, dass es die ursprüngliche Signatur mit der einer leeren Datei vergleicht, um zwischen einer Dateilöschung und einer Änderung an einer tatsächlich leeren Datei zu unterscheiden.
Wenn man dennoch jedes Backup so einrichten möchte, dass es nur die Dateien enthält, die unterschiedlich sind (hinzugefügt oder geändert), dann kann man den --link-dest
verwenden oben beschriebene Lösung und löschen Sie dann die Hardlinks mit etwas wie dem Folgenden:
find $new_backup -type f ! -links 1 -delete
[1] Genau genommen verwenden sie zusätzlichen Platz in Form von doppelten Metadaten, wie dem Dateinamen und dergleichen. Ich denke jedoch, dass jeder das für unbedeutend halten würde.
Und warum ziehen Sie git
nicht in Betracht selbst?
Die von Ihnen beschriebene Strategie hat nach einer vollständigen und zwei inkrementellen Sicherungen ihre Komplikationen, wenn Sie fortfahren. Es ist leicht, Fehler zu machen, und es kann je nach Änderungen sehr ineffizient werden. Es müsste eine Art Rotation geben, dh ab und zu macht man ein neues Voll-Backup - und will man dann das alte behalten oder nicht?
Angesichts einer funktionierenden dir "testdir", das ein Projekt enthält (Dateien und Unterverzeichnisse), git
macht standardmäßig einen versteckten .git
Unterverzeichnis für die Daten. Das wäre für die lokale, zusätzliche Versionskontrolle Merkmale. Zur Sicherung können Sie es auf ein Medium archivieren/wegkopieren oder über das Netzwerk klonen.
Die Revisionskontrolle Sie erhalten (ohne danach zu fragen) einen Nebeneffekt von gits differenziellem Speicher.
Sie können alle Gabelungen/Verzweigungen usw. weglassen. Dies bedeutet, dass Sie einen Zweig namens "Master" haben.
Bevor Sie committen können (eigentlich in das Git-Archiv/Repo schreiben), müssen Sie einen minimalen Benutzer für die Konfigurationsdatei konfigurieren. Dann sollten Sie zuerst in einem Unterverzeichnis (vielleicht tmpfs) lernen und testen. Git ist manchmal genauso knifflig wie tar.
Wie auch immer, wie ein Kommentar sagt:Sichern ist einfach, der schwierige Teil ist das Wiederherstellen.
Nachteile von Git wären nur der kleine Overkill/Overkill.
Vorteile sind:git tracks Inhalt und Dateinamen. Es speichert nur das Notwendige basierend auf einem Diff (zumindest für Textdateien).
Beispiel
Ich habe 3 Dateien in einem Verzeichnis. Nach git init
, git add .
und git commit
Ich habe ein 260K .git
dir.
Dann habe ich cp -r .git /tmp/abpic.git
(ein guter Ort, um ein Backup zu speichern:). Ich rm
das 154K jpg, und auch ändern eine Textdatei. Ich auch rm -r .git
.
]# ls
atext btext
]# git --git-dir=/tmp/abpic.git/ ls-files
atext
btext
pic154k.jpg
Vor dem Wiederherstellen der Dateien kann ich die genauen Unterschiede abrufen:
]# git --git-dir=/tmp/abpic.git/ status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: atext
deleted: pic154k.jpg
no changes added to commit (use "git add" and/or "git commit -a")
Hier möchte ich dem git restore
folgen Hinweis.
Nach git --git-dir=/tmp/abpic.git/ restore \*
:
]# ls -st
total 164
4 atext 156 pic154k.jpg 4 btext
Das JPEG ist zurück und die Textdatei btext
hat nicht wurde aktualisiert (hält den Zeitstempel). Die Änderungen in atext
werden überschrieben.
Um das Repo und das (Arbeits-) Verzeichnis wieder zusammenzuführen, können Sie es einfach zurückkopieren.
]# cp -r /tmp/abpic.git/ .git
]# git status
On branch master
nothing to commit, working tree clean
Die Dateien im aktuellen Verzeichnis sind identisch mit .git
Archiv (nach dem restore
). Neue Änderungen werden angezeigt und können ohne Planung hinzugefügt und übernommen werden. Sie müssen es nur zu Sicherungszwecken auf einem anderen Medium speichern.
Nachdem eine Datei geändert wurde, können Sie status
verwenden oder diff
:
]# echo more >>btext
]# git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: btext
no changes added to commit (use "git add" and/or "git commit -a")
]# git diff
diff --git a/btext b/btext
index 96b5d76..a4a6c5b 100644
--- a/btext
+++ b/btext
@@ -1,2 +1,3 @@
This is file b
second line
+more
#]
Und genau wie git
von "+more" in der Datei 'btext' weiß, wird diese Zeile auch nur inkrementell gespeichert.
Nach git add .
(oder git add btext
) der status
Befehl wechselt von rot auf grün und der commit
gibt dir die Info.
]# git add .
]# git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: btext
]# git commit -m 'btext: more'
[master fad0453] btext: more
1 file changed, 1 insertion(+)
Und irgendwie kommt man wirklich an den Inhalt heran:
]# git ls-tree @
100644 blob 321e55a5dc61e25fe34e7c79f388101bd1ae4bbf atext
100644 blob a4a6c5bd3359d84705e5fd01884caa8abd1736d0 btext
100644 blob 2d550ffe96aa4347e465109831ac52b7897b9f0d pic154k.jpg
Und dann die ersten 4 Hex-Hash-Ziffern
]# git cat-file blob a4a6
This is file b
second line
more
Um einen Commit in der Zeit zurück zu reisen ist es:
]# git ls-tree @^
100644 blob 321e55a5dc61e25fe34e7c79f388101bd1ae4bbf atext
100644 blob 96b5d76c5ee3ccb7e02be421e21c4fb8b96ca2f0 btext
100644 blob 2d550ffe96aa4347e465109831ac52b7897b9f0d pic154k.jpg
]# git cat-file blob 96b5
This is file b
second line
Der Blob von btext hat vor dem letzten Commit einen anderen Hash, die anderen haben den gleichen.
Eine Übersicht wäre:
]# git log
commit fad04538f7f8ddae1f630b648d1fe85c1fafa1b4 (HEAD -> master)
Author: Your Name <[email protected]>
Date: Sun Feb 16 10:51:51 2020 +0000
btext: more
commit 0bfc1837e20988f1b80f8b7070c5cdd2de346dc7
Author: Your Name <[email protected]>
Date: Sun Feb 16 08:45:16 2020 +0000
added 3 files with 'add .'
Anstelle von manuell mit einem Zeitstempel versehenen Tar-Dateien haben Sie Commits mit einer Nachricht und einem Datum (und einem Autor). Logisch an diese Commits angehängt sind die Dateilisten und Inhalte.
Einfach git
ist 20 % komplizierter als tar
, dafür bekommt man aber entscheidende 50% mehr Funktionalität.
Ich wollte die dritte Änderung von OP vornehmen:eine Datei plus zwei neue 'Bild'-Dateien ändern. Habe ich, aber jetzt habe ich:
]# git log
commit deca7be7de8571a222d9fb9c0d1287e1d4d3160c (HEAD -> master)
Author: Your Name <[email protected]>
Date: Sun Feb 16 17:56:18 2020 +0000
didn't add the pics before :(
commit b0355a07476c8d8103ce937ddc372575f0fb8ebf
Author: Your Name <[email protected]>
Date: Sun Feb 16 17:54:03 2020 +0000
Two new picture files
Had to change btext...
commit fad04538f7f8ddae1f630b648d1fe85c1fafa1b4
Author: Your Name <[email protected]>
Date: Sun Feb 16 10:51:51 2020 +0000
btext: more
commit 0bfc1837e20988f1b80f8b7070c5cdd2de346dc7
Author: Your Name <[email protected]>
Date: Sun Feb 16 08:45:16 2020 +0000
added 3 files with 'add .'
]#
Also, was genau hat dieser Your Name Guy bei seinen beiden Commits kurz vor 18 Uhr gemacht?
Die Details des letzten Commits sind:
]# git show
commit deca7be7de8571a222d9fb9c0d1287e1d4d3160c (HEAD -> master)
Author: Your Name <[email protected]>
Date: Sun Feb 16 17:56:18 2020 +0000
didn't add the pics before :(
diff --git a/picture2 b/picture2
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/picture2
@@ -0,0 +1 @@
+1
diff --git a/picture3 b/picture3
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/picture3
@@ -0,0 +1 @@
+2
]#
Und um den vorletzten Commit zu prüfen, dessen Meldung zwei Bilder ankündigt:
]# git show @^
commit b0355a07476c8d8103ce937ddc372575f0fb8ebf
Author: Your Name <[email protected]>
Date: Sun Feb 16 17:54:03 2020 +0000
Two new picture files
Had to change btext...
diff --git a/btext b/btext
index a4a6c5b..de7291e 100644
--- a/btext
+++ b/btext
@@ -1,3 +1 @@
-This is file b
-second line
-more
+Completely changed file b
]#
Dies geschah, weil ich git commit -a
ausprobiert habe um git add .
abzukürzen , und die beiden Dateien waren neu (ungetrackt). Es wurde rot mit git status
angezeigt , aber wie gesagt, git ist nicht weniger knifflig als tar oder unix.
"Ihre Debütantin weiß einfach, was Sie brauchen, aber ich weiß, was Sie wollen" (oder umgekehrt. Wichtig ist, dass es nicht immer dasselbe ist)