como obter o rsync para vincular arquivos idênticos com a opção --link-dest se um arquivo antigo já existir?

9

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.

    
por math 30.03.2015 / 07:33

1 resposta

11

(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.

    
por 03.03.2017 / 17:12

Tags