Ačkoli tar
má přírůstkový režim, existuje několik komplexnějších nástrojů, které tuto práci vykonávají:
- Duplicita
- Duplikáty
Podporují nejen přírůstkové zálohování, ale je také snadné nakonfigurovat plán, podle kterého je třeba provést úplnou zálohu. Například v duplicity
:duplicity --full-if-older-than 1M
zajistí spuštění úplné zálohy. Podporují také návrat v čase ke konkrétnímu souboru, s obyčejným tarem budete muset projít všechny přírůstkové soubory, dokud nenajdete ten, který obsahuje správný soubor.
Kromě toho podporují šifrování a nahrávání do různých backendů (jako je sftp, úložiště objektů blob atd.). Samozřejmě pokud šifrujete, nezapomeňte si dobře zálohovat své klíče do sekundární zálohy!
Dalším důležitým aspektem je, že můžete ověřit integritu svých záloh a zajistit, že je budete moci obnovit, např. pomocí duplicity verify
.
Negativně bych doporučil strategii zálohování založenou na git. Velké obnovy zaberou značný čas.
Zkoušel jsem rsync, ale nezdá se, že by mohl dělat to, co chci, nebo spíše nevím, jak to udělat.
Vím, že bych pravděpodobně mohl vytvořit skript, který spustí rozdíl a poté vybere soubory k zálohování na základě výsledku (nebo efektivněji, stačí získat kontrolní součet a porovnat), ale chci vědět, jestli existuje nějaký nástroj, který to dokáže trochu jednodušší :)
rsync
je přesně ten program, který kopíruje na základě rozdílu. Ve výchozím nastavení kopíruje pouze v případě, že existuje rozdíl v čase nebo velikosti poslední změny, ale může se dokonce porovnávat pomocí kontrolního součtu s -c
.
Problém je v tom, že jste tar
zálohování. To bude snazší, pokud to neuděláte. Ani nevím, proč to děláš. Může to mít smysl, pokud je komprimujete, ale ani to neděláte.
V článku Wikipedie o přírůstkových zálohách je uveden příklad rsync
příkaz, který zní zhruba takto:
rsync -va \
--link-dest="$dst/2020-02-16--05-10-45--testdir/" \
"$src/testdir/" \
"$dst/2020-02-17--03-24-16--testdir/"
Co dělá, je pevné propojení souborů z předchozí zálohy, když jsou nezměněny od zdroje. Je zde také --copy-dest
pokud chcete, aby se místo toho zkopírovalo (je to stále rychlejší, když $dst
je vzdálený nebo na rychlejším disku).
Pokud používáte souborový systém s dílčími svazky, jako je btrfs, můžete také před rsync'ing pouze pořídit snímek z předchozí zálohy. Snímky jsou okamžité a nezabírají další místo[1].
btrfs subvolume snapshot \
"$dst/2020-02-16--05-10-45--testdir" \
"$dst/2020-02-17--03-24-16--testdir"
Nebo pokud používáte souborový systém, který podporuje reflinky, jako je ext4, můžete to udělat také. Reflinky se provádějí vytvořením nového inodu, ale odkazováním na stejné bloky jako zdrojový soubor, implementující podporu COW. Je stále rychlejší než běžné kopírování, protože nečte a nezapisuje data a také nezabírá další místo[1].
cp --reflink -av \
"$dst/2020-02-16--05-10-45--testdir" \
"$dst/2020-02-17--03-24-16--testdir"
Každopádně, jakmile něco takového uděláte, můžete udělat obyčejný rsync
pro zkopírování rozdílů:
rsync -va \
"$src/testdir/" \
"$dst/2020-02-17--03-24-16--testdir/"
Možná budete chtít přidat --delete
, což by způsobilo, že rsync odstraní soubory z cíle, které již nejsou přítomny ve zdroji.
Další užitečnou možností je -i
nebo --itemize-changes
. Vytváří stručný, strojově čitelný výstup, který popisuje, jaké změny rsync dělá. Obvykle přidávám tuto možnost a potrubí jako:
rsync -Pai --delete \
"$src/testdir/" \
"$dst/2020-02-17--03-24-16--testdir/" \
|& tee -a "$dst/2020-02-17--03-24-16--testdir.log"
pro uchování záznamů o změnách pomocí snadno grep
schopné soubory. |&
je potrubí stdout i stderr.
-P
je zkratka pro --partial
a --progress
. --partial
uchovává částečně přenesené soubory, ale co je důležitější --progress
hlásí průběh jednotlivých souborů.
Jak se to srovnává s archivací změn pomocí tar
Výše uvedená řešení vedou k adresářům, které vypadají, že obsahují vše. I když je tomu tak, v součtu pro jakékoli množství/frekvenci záloh by zabíraly přibližně stejné množství místa jako obyčejné archivy tar pouze se změnami. Je to kvůli tomu, jak fungují pevné odkazy, reflinky a snímky. Použití šířky pásma při vytváření záloh by bylo také stejné.
Výhody jsou:
- zálohy lze snadno obnovit pomocí nástroje rsync a jsou rychlejší, protože nástroj rsync přenese pouze rozdíly ze zálohy.
- je jednodušší je procházet a v případě potřeby upravovat.
- Odstranění souborů lze přirozeně zakódovat jako nepřítomnost souboru v nových zálohách. Při použití archivů tar by se člověk musel uchýlit k hackům, jako je smazání souboru
foo
, označte jejfoo.DELETED
nebo udělat něco složitého. Nikdy jsem například nepoužil duplicitu, ale při pohledu na dokumentaci se zdá, že kóduje mazání přidáním prázdného souboru stejného jména do nového tar a uložením původního podpisu souboru do samostatného souboru .sigtar. Představuji si, že porovnává původní podpis s podpisem prázdného souboru, aby se rozlišilo mezi smazáním souboru a změnou na skutečný prázdný soubor.
Pokud stále chcete nastavit každou zálohu tak, aby obsahovala pouze soubory, které se liší (přidané nebo upravené), můžete použít --link-dest
řešení popsané výše a poté odstraňte pevné odkazy pomocí něčeho podobného:
find $new_backup -type f ! -links 1 -delete
[1] Přesně řečeno, využívají další prostor ve formě duplicitních metadat, jako je název souboru a podobně. Myslím si však, že by to někdo považoval za nepodstatné.
A proč nezvažujete git
sám?
Strategie, kterou popisujete, má po jedné úplné a dvou přírůstkových zálohách své komplikace, když budete pokračovat. Je snadné dělat chyby a může být velmi neefektivní, v závislosti na změnách. Muselo by dojít k jakési rotaci, tj. čas od času uděláte novou plnou zálohu - a chcete si pak tu starou ponechat nebo ne?
Vzhledem k tomu, že funguje dir "testdir" obsahující nějaký projekt (soubory a podadresáře), git
vytváří ve výchozím nastavení skrytý .git
podadresář pro data. To by bylo pro místní, další řízení verzí funkce. Pro zálohování jej můžete archivovat/zkopírovat na médium nebo jej naklonovat přes síť.
Řízení revizí dostanete (aniž byste o to žádali) je vedlejší efekt rozdílového úložiště git.
Můžete vynechat veškeré rozvětvení/větvení a tak dále. To znamená, že máte jednu větev s názvem „master“.
Než budete moci odevzdat (ve skutečnosti zapisovat do git archivu/repo), musíte nakonfigurovat minimálního uživatele pro konfigurační soubor. Pak byste se měli nejprve naučit a otestovat v podadresáři (možná tmpfs). Git je někdy stejně složitý jako tar.
Každopádně, jak říká komentář:zálohování je snadné, těžká část je obnovení.
Nevýhody git by byly jen malá režie/nadměrná práce.
Výhody jsou:git tracks obsah a názvy souborů. Uloží pouze to, co je nezbytné, na základě rozdílu (alespoň pro textové soubory).
Příklad
Mám 3 soubory v adresáři. Po git init
, git add .
a git commit
Mám 260 kB .git
dir.
Pak jsem cp -r .git /tmp/abpic.git
(dobré místo pro uložení zálohy:). I rm
154K jpg a také změnit jeden textový soubor. Také rm -r .git
.
]# ls
atext btext
]# git --git-dir=/tmp/abpic.git/ ls-files
atext
btext
pic154k.jpg
Před obnovením souborů mohu získat přesné rozdíly:
]# 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")
Zde se chci řídit git restore
nápověda.
Po git --git-dir=/tmp/abpic.git/ restore \*
:
]# ls -st
total 164
4 atext 156 pic154k.jpg 4 btext
Jpeg je zpět a textový soubor btext
není aktualizováno (uchovává časové razítko). Úpravy v atext
jsou přepsány.
Chcete-li znovu sjednotit repo a (pracovní) adresář, stačí jej zkopírovat zpět.
]# cp -r /tmp/abpic.git/ .git
]# git status
On branch master
nothing to commit, working tree clean
Soubory v aktuálním adresáři jsou totožné se soubory .git
archiv (za restore
). Nové změny se zobrazí a lze je přidat a potvrdit bez jakéhokoli plánování. Musíte jej pouze uložit na jiné médium pro účely zálohování.
Po úpravě souboru můžete použít status
nebo 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
#]
A stejně jako git
ví o "+more" v souboru 'btext', bude také ukládat tento řádek pouze přírůstkově.
Po git add .
(nebo git add btext
) status
příkaz se přepne z červené na zelenou a commit
vám poskytne informace.
]# 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(+)
A můžete se opravdu nějak dostat k obsahu:
]# git ls-tree @
100644 blob 321e55a5dc61e25fe34e7c79f388101bd1ae4bbf atext
100644 blob a4a6c5bd3359d84705e5fd01884caa8abd1736d0 btext
100644 blob 2d550ffe96aa4347e465109831ac52b7897b9f0d pic154k.jpg
A pak první 4 hexadecimální hash číslice
]# git cat-file blob a4a6
This is file b
second line
more
Cestování zpět v čase jedním potvrzením je:
]# 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
Blob btext má před posledním odevzdáním jiný hash, ostatní mají stejný.
Přehled by byl:
]# 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 .'
Místo ručně označovaných tar souborů máte commity se zprávou a datem (a autorem). K těmto odevzdáním jsou logicky připojeny seznamy souborů a obsah.
Jednoduché git
je o 20 % složitější než tar
, ale získáte rozhodujících o 50 % více funkcí.
Chtěl jsem provést třetí změnu OP:změnit soubor plus dva nové soubory „obrázků“. Ano, ale teď mám:
]# 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 .'
]#
Takže co přesně ten Your Name Guy udělal ve svých dvou commitech krátce před 18:00?
Podrobnosti posledního potvrzení jsou:
]# 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
]#
A pro kontrolu předposledního odevzdání, jehož zpráva oznamuje dva obrázky:
]# 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
]#
Stalo se to, protože jsem zkusil git commit -a
na zkratku git add .
a dva soubory byly nové (nesledovaný). Byl zobrazen červeně s git status
, ale jak říkám, git není méně komplikovaný než tar nebo unix.
"Váš debutant prostě ví, co potřebujete, ale já vím, co chcete" (nebo naopak. Důležité je, že to není vždy stejné)