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

23

De tempos em tempos, tenho que executar várias grandes alterações de migração nos 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 links físicos para todos os arquivos originais (alguns deles são grandes) e posso sobrescrever na árvore de destino apenas os arquivos que precisam ser migrados. No final, eu posso alternar com segurança dos arquivos antigos para os novos com duas mvoperações.

No entanto, não consigo obter o rsync para 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 um problema ao usar o mesmo diretório de origem e link-dest?

Jean-Philippe Pellet
fonte

Respostas:

21

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

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

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

[Agora, apenas um breve aparte sobre rsynca estranheza de. Observe a trilha /adicionada ao argumento de origem. Isso diz rsyncpara trabalhar com o conteúdo do diretório de origem, em vez de com o próprio diretório de origem. (Suponho que $DATAainda não contenha um final /). Nesse caso, queremos trabalhar com o conteúdo e adicionamos o final /.]

Se, por outro lado, $DATAfor um caminho relativo (ou seja, não começa com a /), o comentário de Sean R --link-desté sobre: ​​O caminho de destino do link é interpretado em relação ao caminho de destino , portanto, você deve usar o seguinte:

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

EDITAR

Uma observação final: verifica-se que a segunda rsynclinha de comando que eu dei deve funcionar independentemente de $DATAser um caminho absoluto, uma vez basenameque não se importa se um caminho é absoluto ou relativo.

Steven segunda-feira
fonte
1
Apenas uma barra faltando, quem teria pensado nisso… Obrigado pela boa explicação!
Jean-Philippe Pellet
Obrigado por isso, tentei seguir várias instruções de backup incremental, como esta, e não encontrei nenhuma menção a essa peculiaridade. Essa foi a única coisa que realmente garantiu que os arquivos estavam sendo vinculados. Verificando que a contagem ref foi> 1 e inode números eram os mesmos comls -ilah
Walf
I utilizado este em conjunto com a função relPath () descrito no unix.stackexchange.com/a/85068/57414 a cópia de segurança de um $SOURCEdirectório numa $TARGETdir assim:SOURCE='abs_path_to_backup'; TARGET='.'; rsync -a --link-dest=$(relpath $TARGET $SOURCE) $SOURCE/ $TARGET/
Nathan S. Watson-Haigh
13

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

cp -al $DATA/ $DATA/../upgrade_tmp/
  • -a se repete como rsync -a
  • -l vinculará os arquivos ao invés de copiá-los.
Sean Reifschneider
fonte
1
cp -alinfelizmente não está disponível no meu sistema (Mac OS X 10.6). Em vez disso, vou usar pax ...
Jean-Philippe Pellet
7

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

rsync -a --link-dest=../`basename $DATA` $DATA $DATA/../upgrade_tmp
Sean Reifschneider
fonte
Opa, eu quis dizer basename, originalmente eu tinha dirname.
Sean Reifschneider
1
A página de manual diz que a --link-destopção, se relativa , é relativa ao diretório de destino. No meu caso, é absoluto. Mesmo torná-lo relativo ao diretório de destino não faz esse trabalho.
Jean-Philippe Pellet
7

Acontece que é mais difícil fazer isso do rsyncque com outras ferramentas. A resposta correta rsyncé a de Steven Monai, mas a maneira mais fácil de fazer isso é usar um cp -alou pax -rwlem sistemas onde -lnão é uma opção válida para cp:

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

ou

cp -al $DATA/ $DATA/../upgrade_tmp/
Jean-Philippe Pellet
fonte
4

Funciona para mim:

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

Eu uso o rsync versão 3.1.0.

Do homem :

--hard-links

Diz ao rsync para procurar arquivos vinculados na transferência, sem essa opção, os arquivos vinculados na transferência são tratados como se fossem arquivos separados.

--link-dest = DIR

Arquivos inalterados são vinculados do DIR ao diretório de destino. Os arquivos devem ser idênticos em todos os atributos preservados (por exemplo, permissões, possivelmente propriedade) para que os arquivos sejam vinculados

Alexander Fedorov
fonte
2
Somente o snippet de código não é suficiente, explique o que faz e por quê.
peterh diz restabelecer Monica
--hard-links Diz ao rsync para procurar arquivos vinculados na transferência, sem essa opção, os arquivos vinculados na transferência são tratados como se fossem arquivos separados. --link-dest = DIR Arquivos inalterados são vinculados do DIR ao diretório de destino. Os arquivos devem ser idênticos em todos os atributos preservados (por exemplo, permissões, possivelmente propriedade) para que os arquivos sejam vinculados.
Alexander Fedorov
1
Maravilhoso. Obrigado. Na verdade, encontrei sua resposta na fila "baixa qualidade". Isso significa que houve uma votação se sua resposta deve ser excluída ou não. Mas não apenas o perigo das exclusões é um motivo para tentar dar uma resposta "humana" bem formatada, mas também ajuda muito se você deseja coletar votos positivos.
peterh diz restabelecer Monica
2

Pode tentar seguir o link http://www.lessfs.com/wordpress/ é um trabalho em COW (cópia na gravação) que economizará tempo e espaço

Rajat
fonte
lessfs é muito interessante, mas também é muito experimental. Ainda não é recomendado para uso em produção.
precisa saber é o seguinte
2

Primeiro, crie os diretórios apenas no destino:

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

Em seguida, vincule apenas os arquivos:

cd /source
find . -type f -exec ln -v {} /destination/{} \;
Cakemox
fonte
Obrigado - na verdade, eu poderia usar paxcomo mostrado no meu comentário acima, o que parece mais fácil.
Jean-Philippe Pellet
1

Use a opção -H para preservar os Hardlinks e leia a página de manual.

tex
fonte
1
-H não funciona. Não tenho hardlinks para preservar na minha árvore de origem, só quero uma cópia simples da minha árvore de origem, onde, na cópia, todos os arquivos são vinculados aos arquivos originais. Desculpe na minha pergunta original não estava claro ...
Jean-Philippe Pellet
"leia a página de manual" é uma resposta? :-)
meduz