Como posso usar o rsync para duplicar uma árvore de diretórios, criando hardlinks para arquivos?

20

Ocasionalmente, tenho que executar várias alterações de migração em arquivos de dados no meu servidor, e estou procurando uma boa maneira de fazer isso. Eu estava pensando em usar o rsync para duplicar minha estrutura de diretórios, começando na pasta de dados raiz, criando hard links para todos os arquivos originais (alguns deles são bastante grandes), e posso sobrescrever na árvore de destino apenas os arquivos que precisam ser migrados. No final, posso alternar com segurança dos arquivos antigos para os novos arquivos com duas mv de operações.

No entanto, parece que não consigo fazer o rsync fazer isso. Eu tentei

rsync -a --link-dest=$DATA $DATA $DATA/../upgrade_tmp

mas, em vez de criar links físicos para arquivos, o rsync os copia completamente. Existe algum problema ao usar o mesmo diretório source e link-dest?

    
por Jean-Philippe Pellet 07.12.2010 / 11:09

8 respostas

18

rsync é uma ferramenta poderosa, mas, infelizmente, é estranhamente exigente em alguns de seus nomes de caminho.

Se $DATA for um caminho absoluto (ou seja, começa com / ), a linha de comando correta a ser usada é:

rsync -a --link-dest=$DATA $DATA/ $DATA/../upgrade_tmp

[Agora, apenas um breve resumo sobre a estranheza de rsync . Observe o / à direita adicionado ao argumento de origem. Isso diz a rsync para trabalhar com o conteúdo do diretório de origem, em vez de usar o próprio diretório de origem. (Eu estou supondo que $DATA não contém um / ). Nesse caso, queremos trabalhar com o conteúdo, então adicionamos o / .]

Se, por outro lado, $DATA for um caminho relativo (isto é, ele não começa com / ), então o comentário de Sean R sobre --link-dest está ativado: O caminho link-dest é interpretado como relativo para o caminho destino , assim você usaria o seguinte:

rsync -a --link-dest=../'basename $DATA' $DATA/ $DATA/../upgrade_tmp

EDITAR

Uma observação final é que a segunda linha de comando rsync que eu dei deve funcionar independentemente de $DATA ser um caminho absoluto, pois basename não se importa se um caminho é absoluto ou relativo.

    
por 07.12.2010 / 18:09
11

O que você quer é "cp -al":

cp -al $DATA/ $DATA/../upgrade_tmp/
  • -a recurses como rsync -a
  • -l ligará arquivos em vez de copiá-los.
por 07.12.2010 / 14:05
6

A opção --link-dest em rsync é relativa ao diretório destino , não ao diretório atual. Então o que você quer é:

rsync -a --link-dest=../'basename $DATA' $DATA $DATA/../upgrade_tmp
    
por 07.12.2010 / 14:53
6

Acontece que é mais difícil fazer isso com rsync do que com outras ferramentas. A resposta correta para rsync é de Steven Monai, mas a maneira mais fácil de fazer isso é usar cp -al ou pax -rwl em sistemas onde -l não é uma opção válida para cp :

pax -rwl $DATA $DATA/../upgrade_tmp

ou

cp -al $DATA/ $DATA/../upgrade_tmp/
    
por 08.12.2010 / 09:35
2

Funciona para mim:

$ rsync --hard-links --recursive --link-dest=/local user@host:/remote/ /local

Eu uso o rsync versão 3.1.0.

De homem :

--hard-links

Tells rsync to look for hard-linked files in the transfer, without this option, hard-linked files in the transfer are treated as though they were separate files.

--link-dest=DIR

Unchanged files are hard linked from DIR to the destination directory. The files must be identical in all preserved attributes (e.g. permissions, possibly ownership) in order for the files to be linked together

    
por 24.04.2015 / 18:43
1

Pode tentar seguir o link link que funciona em COW (copy on write) que economizará tempo e espaço

    
por 07.12.2010 / 11:17
1

Primeiro, crie os diretórios somente no destino:

rsync -av --include '*/' --exclude '*' /source/ /destination/

Em seguida, vincule os arquivos apenas:

cd /source
find . -type f -exec ln -v {} /destination/{} \;
    
por 07.12.2010 / 13:07
0

Use a opção -H para preservar os hardlinks e ler a página do manual.

    
por 07.12.2010 / 11:30