Sebbene tar
ha una modalità incrementale ci sono un paio di strumenti più completi per fare il lavoro:
- Duplicità
- Duplicati
Non solo supportano i backup incrementali, è facile configurare una pianificazione in base alla quale è necessario eseguire un backup completo. Ad esempio in duplicity
:duplicity --full-if-older-than 1M
si assicurerà che sia stato eseguito un backup completo. Supportano anche il ritorno indietro nel tempo a un file specifico, con tar semplice dovrai esaminare tutti i file incrementali finché non ne trovi uno che contiene il file giusto.
Inoltre supportano la crittografia e il caricamento su una varietà di back-end (come sftp, archiviazione BLOB, ecc.). Ovviamente se crittografi, non dimenticare di fare un buon backup delle tue chiavi su un backup secondario!
Un altro aspetto importante è che puoi verificare l'integrità dei tuoi backup, assicurandoti di poterli ripristinare, ad esempio utilizzando duplicity verify
.
Consiglierei negativamente una strategia di backup basata su git. Ripristini di grandi dimensioni richiedono molto tempo.
Ho provato rsync, ma non sembra essere in grado di fare quello che voglio o, più probabilmente, non so come farlo.
So che probabilmente potrei creare uno script che esegue un diff e quindi seleziona i file di cui eseguire il backup in base al risultato (o in modo più efficiente, basta ottenere un checksum e confrontare), ma voglio sapere se esiste qualche utilità che può farlo a un po' più facile :)
rsync
è proprio quel programma che copia in base a un diff. Per impostazione predefinita, copia solo quando c'è una differenza nell'ora o nella dimensione dell'ultima modifica, ma può anche confrontare tramite checksum con -c
.
Il problema qui è che hai tar
'ing i backup. Questo diventa più facile se non lo fai. Non so nemmeno perché lo stai facendo. Potrebbe avere senso se li stai comprimendo, ma non lo stai nemmeno facendo.
L'articolo di Wikipedia per i backup incrementali ha un esempio rsync
comando che va all'incirca:
rsync -va \
--link-dest="$dst/2020-02-16--05-10-45--testdir/" \
"$src/testdir/" \
"$dst/2020-02-17--03-24-16--testdir/"
Quello che fa è collegare i file dal backup precedente quando sono invariati rispetto all'origine. C'è anche --copy-dest
se invece vuoi che venga copiato (è ancora più veloce quando $dst
è un disco remoto o su un'unità più veloce).
Se usi un filesystem con sottovolumi come btrfs, puoi anche fare un'istantanea dal backup precedente prima di rsync'ing. Le istantanee sono istantanee e non occupano spazio aggiuntivo[1].
btrfs subvolume snapshot \
"$dst/2020-02-16--05-10-45--testdir" \
"$dst/2020-02-17--03-24-16--testdir"
Oppure, se stai utilizzando un filesystem che supporta i reflink, come ext4, puoi farlo anche tu. I reflink vengono eseguiti creando un nuovo inode ma facendo riferimento agli stessi blocchi del file sorgente, implementando il supporto COW. È ancora più veloce della copia normale perché non legge e scrive i dati e inoltre non occupa spazio aggiuntivo[1].
cp --reflink -av \
"$dst/2020-02-16--05-10-45--testdir" \
"$dst/2020-02-17--03-24-16--testdir"
Ad ogni modo, una volta che hai fatto qualcosa del genere puoi semplicemente fare un normale rsync
per copiare le differenze:
rsync -va \
"$src/testdir/" \
"$dst/2020-02-17--03-24-16--testdir/"
Tuttavia, potresti voler aggiungere --delete
, che farebbe sì che rsync elimini i file dalla destinazione che non sono più presenti nell'origine.
Un'altra opzione utile è -i
o --itemize-changes
. Produce un output succinto e leggibile dalla macchina che descrive quali modifiche sta facendo rsync. Normalmente aggiungo quell'opzione e pipe come:
rsync -Pai --delete \
"$src/testdir/" \
"$dst/2020-02-17--03-24-16--testdir/" \
|& tee -a "$dst/2020-02-17--03-24-16--testdir.log"
per tenere traccia delle modifiche facilmente tramite grep
file in grado. Il |&
è reindirizzare sia stdout che stderr.
Il -P
è l'abbreviazione di --partial
e --progress
. --partial
mantiene i file parzialmente trasferiti, ma soprattutto --progress
riporta l'avanzamento per file.
Confronto con l'archiviazione delle modifiche con tar
Le soluzioni di cui sopra si traducono in directory che sembrano contenere tutto. Anche se è così, in totale per qualsiasi quantità/frequenza di backup, occuperebbero all'incirca la stessa quantità di spazio di archivi tar semplici con solo modifiche. Ciò è dovuto al modo in cui funzionano gli hardlink, i reflink e gli snapshot. Anche l'uso della larghezza di banda durante la creazione dei backup sarebbe lo stesso.
I vantaggi sono:
- i backup sono facili da ripristinare con rsync e più veloci, poiché rsync trasferirebbe solo le differenze dal backup.
- sono più semplici da sfogliare e modificare se necessario.
- le eliminazioni di file possono essere codificate naturalmente come l'assenza del file nei nuovi backup. Quando si utilizzano gli archivi tar, si dovrebbe ricorrere a hack, come eliminare un file
foo
, contrassegnalo comefoo.DELETED
o fare qualcosa di complicato. Ad esempio, non ho mai usato la duplicità, ma guardando la sua documentazione, sembra che codifichi le eliminazioni aggiungendo un file vuoto con lo stesso nome nel nuovo tar e conservando la firma originale del file in un file .sigtar separato. Immagino che confronti la firma originale con quella di un file vuoto per distinguere tra l'eliminazione di un file e una modifica a un file vuoto effettivo.
Se si desidera comunque configurare ogni backup in modo che contenga solo i file diversi (aggiunti o modificati), è possibile utilizzare --link-dest
soluzione descritta sopra e quindi eliminare i collegamenti fisici utilizzando qualcosa di simile al seguente:
find $new_backup -type f ! -links 1 -delete
[1] A rigor di termini, usano spazio aggiuntivo sotto forma di metadati duplicati, come il nome del file e simili. Tuttavia, penso che chiunque lo considererebbe insignificante.
E perché non stai considerando git
si?
La strategia che descrivi, dopo un backup completo e due incrementali, ha le sue complicazioni quando continui. È facile commettere errori e può diventare molto inefficiente, a seconda delle modifiche. Ci dovrebbe essere una sorta di rotazione, cioè di tanto in tanto fai un nuovo backup completo - e poi vuoi mantenere quello vecchio o no?
Dato un funzionante dir "testdir" contenente alcuni progetti (file e sottocartelle), git
crea di default un .git
nascosto subdir per i dati. Sarebbe per il controllo di versione locale aggiuntivo caratteristiche. Per il backup, puoi archiviarlo/copiarlo su un supporto o clonarlo tramite rete.
Il controllo di revisione ottieni (senza chiedere) è un effetto collaterale dell'archiviazione differenziale di git.
Puoi tralasciare tutte le biforcazioni / ramificazioni e così via. Ciò significa che hai un ramo chiamato "master".
Prima di poter eseguire il commit (in realtà scrivere nell'archivio/repo git), è necessario configurare un utente minimo per il file di configurazione. Quindi dovresti prima imparare e testare in una sottodirectory (forse tmpfs). Git è complicato quanto tar, a volte.
Ad ogni modo, come dice un commento:il backup è facile, la parte difficile è il ripristino.
Gli svantaggi di git sarebbero solo il piccolo sovraccarico/eccessivo.
I vantaggi sono:git tracce contenuti e nomi di file. Salva solo ciò che è necessario, basato su un diff (almeno per i file di testo).
Esempio
Ho 3 file in una directory. Dopo git init
, git add .
e git commit
Ho un .git
da 260K dir.
Poi ho cp -r .git /tmp/abpic.git
(un buon posto per salvare un backup:). Io rm
il jpg da 154K e anche cambia un file di testo. Ho anche rm -r .git
.
]# ls
atext btext
]# git --git-dir=/tmp/abpic.git/ ls-files
atext
btext
pic154k.jpg
Prima di ripristinare i file posso ottenere le differenze precise:
]# 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")
Qui voglio seguire il git restore
suggerimento.
Dopo git --git-dir=/tmp/abpic.git/ restore \*
:
]# ls -st
total 164
4 atext 156 pic154k.jpg 4 btext
Il jpeg è tornato e il file di testo btext
ha non stato aggiornato (mantiene il timestamp). Le modifiche in atext
vengono sovrascritti.
Per riunire il repository e la directory (funzionante) puoi semplicemente copiarlo di nuovo.
]# cp -r /tmp/abpic.git/ .git
]# git status
On branch master
nothing to commit, working tree clean
I file nella directory corrente sono identici al .git
archivio (dopo restore
). Le nuove modifiche verranno visualizzate e possono essere aggiunte e salvate, senza alcuna pianificazione. Devi solo memorizzarlo su un altro supporto, a scopo di backup.
Dopo che un file è stato modificato, puoi usare status
o 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
#]
E proprio come git
conosce "+more" nel file 'btext', memorizzerà anche quella riga in modo incrementale.
Dopo git add .
(o git add btext
) il status
il comando passa dal rosso al verde e il commit
ti dà le informazioni.
]# 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(+)
E puoi davvero arrivare ai contenuti, in qualche modo:
]# git ls-tree @
100644 blob 321e55a5dc61e25fe34e7c79f388101bd1ae4bbf atext
100644 blob a4a6c5bd3359d84705e5fd01884caa8abd1736d0 btext
100644 blob 2d550ffe96aa4347e465109831ac52b7897b9f0d pic154k.jpg
E poi le prime 4 cifre hash esadecimali
]# git cat-file blob a4a6
This is file b
second line
more
Per viaggiare indietro nel tempo di un commit è:
]# 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
il blob di btext ha un diverso hash prima dell'ultimo commit, gli altri hanno lo stesso.
Una panoramica potrebbe essere:
]# 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 .'
Invece di file tar con timestamp manuale, hai commit con un messaggio e una data (e un autore). Logicamente collegati a questi commit sono gli elenchi e i contenuti dei file.
Semplice git
è il 20% più complicato di tar
, ma ne ottieni il 50% in più di funzionalità decisiva.
Volevo apportare la terza modifica di OP:modificare un file più due nuovi file "immagine". L'ho fatto, ma ora ho:
]# 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 .'
]#
Allora cosa ha fatto esattamente quel Tuo Nome Ragazzo, nei suoi due commit, poco prima delle 18:00?
I dettagli dell'ultimo commit sono:
]# 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
]#
E per controllare il penultimo commit, il cui messaggio annuncia due immagini:
]# 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
]#
Questo è successo perché ho provato git commit -a
per scorciatoia git add .
e i due file erano nuovi (non tracciato). Mostrava in rosso con git status
, ma come ho detto git non è meno complicato di tar o unix.
"La tua debuttante sa di cosa hai bisogno, ma io so cosa vuoi" (o viceversa. Il punto è che non è sempre la stessa cosa)