(convertido da edição da pergunta)
Isso é resolvido atualizando o rsync. A versão 3.1.1 ou posterior agora substituirá os arquivos idênticos no destino e o diretório --link-dest
por um arquivo com link físico. Economiza muito espaço.
Pode-se pensar que --link-dest
'para um arquivo idêntico funcionaria em todos os casos. Mas isso não acontece quando o arquivo existe, mesmo que o arquivo esteja desatualizado / tenha conteúdos diferentes.
É por causa disso, na página man do rsync em --link-dest
:
"This option works best when copying into an empty destination hierarchy, as rsync treats existing files as definitive (so rsync never looks in the link-dest dirs when a destination file already exists)"
Isso significa que se y/file
existir como fonte e z/file
estiver desatualizado,
rsync -a --del -link-dest=y source:/file z
resultará em DOIS inodes (e duas vezes o espaço em disco) sendo usados, y/file
e z/file
, que terão o mesmo conteúdo e data.
Me deparei com isso porque faço backups diários basicamente com esse script executado uma vez por dia:
mv $somedaysago $today;
yest=$today; today='date +%Y%m%d';
rsync -avPShyH --del --link-dest=../$yest host:/dirs $today
Como meus backups atingem até 10 milhões de arquivos, fazer rm -rf $olddir; rsync source:$dir newdir
demora muito (especialmente quando apenas 0,5% dos arquivos mudam por dia, incorrendo na exclusão e criação de 10 milhões de entradas dir apenas para lidar com 50 K novos ou alterados arquivos, o que tornaria meus backups não completos a tempo para o dia seguinte).
Aqui está uma demonstração da situação:
a
é nossa fonte, 1
a 4
são nossos backups numerados:
$ mkdir -p 1 2; echo foo > 1/foobar; cp -lrv 1/* 2
'1/foobar' -> '2/foobar'
$ ls -i1 */foobar
1053003 1/foobar
1053003 2/foobar
$ mkdir a; echo quux > a/foobar
$ mv 1 3; rsync -avPhyH --del --link-dest=../2 a/ 3
sending incremental file list
./
foobar
5 100% 0.00kB/s 0:00:00 (xfer#1, to-check=0/2)
sent 105 bytes received 34 bytes 278.00 bytes/sec
total size is 5 speedup is 0.04
$ ls -i1 */foobar
1053003 2/foobar
1053007 3/foobar
1053006 a/foobar
$ mv 2 4; rsync -avPhyH --del --link-dest=../3 a/ 4
sending incremental file list
./
foobar
5 100% 0.00kB/s 0:00:00 (xfer#1, to-check=0/2)
sent 105 bytes received 34 bytes 278.00 bytes/sec
total size is 5 speedup is 0.04
$ ls -il1 */foobar
1053007 -rw-r--r-- 1 math math 5 Mar 30 00:57 3/foobar
1053008 -rw-r--r-- 1 math math 5 Mar 30 00:57 4/foobar
1053006 -rw-r--r-- 1 math math 5 Mar 30 00:57 a/foobar
$ md5sum [34a]/foobar
d3b07a382ec010c01889250fce66fb13 3/foobar
d3b07a382ec010c01889250fce66fb13 4/foobar
d3b07a382ec010c01889250fce66fb13 a/foobar
Agora, temos dois backups de a/foobar
que são idênticos em todos os aspectos, incluindo timestamp, mas ocupando diferentes inodes.
Pode-se pensar que uma solução seria --delete-before
, o que mata o benefício da varredura incremental, mas isso não ajuda, pois o arquivo não será excluído, mas usado como uma base caso a cópia incremental seja possível. / p>
Pode-se ainda supor que podemos desativar esse hedge de cópia incremental com --whole-file
, mas isso não ajuda o algoritmo, não há como conseguir o que queremos.
Eu considero esse comportamento outro bug no rsync, onde um comportamento benéfico poderia ser interpretado a partir de seleções cuidadosas de vários argumentos de comando, mas o resultado desejado não está disponível.
Infelizmente, uma solução estaria passando de um único rsync como uma operação atômica para um dry-run com -n
, registrando-o, processando esse log como entrada para pré-excluir manualmente todos os arquivos alterados e executando rsync --link-dest
para obter o que queremos - um grande kludge comparado a um único rsync limpo.
Adendo: tentou pré-vincular $yesterday
e $today
no servidor de backup antes do backup em caixas de produção com rsync --link-dest=../$yesterday $yesterday/ $today
- mas o mesmo resultado - qualquer arquivo que existe de qualquer forma, até mesmo 0 comprimento, nunca será removido e link-destinado, em vez disso, uma cópia totalmente nova será feita do sourcedir com um novo inode e usando mais espaço em disco.
Olhando para pax(1)
como uma possível solução de pré-vinculação antes do backup.
Tags rsync