Como rsync arquivos entre dois controles remotos?

54

Gostaria de transferir arquivos entre dois hosts remotos usando no shell local, mas parece que o rsync não suporta sincronização se dois controles remotos forem especificados da seguinte maneira:

$ rsync -vuar host1:/var/www host2:/var/www
The source and destination cannot both be remote.

Que outras soluções alternativas / comandos eu poderia usar para obter resultados semelhantes?

kenorb
fonte
serverfault.com/questions/411552/rsync-remote-to-remote
Ciro Santilli新疆改造中心法轮功六四事件
11
Na verdade, você pode sincronizar entre 2 hosts remotos, utilizando o sshfs em um terceiro host. Basta usar sshfs para montar host1 e host2 no host 3. Em seguida, rsync entre 1 e 2.
William Legg
A desvantagem de usar o @WilliamLegg sshfsé que ele rsyncvê os sistemas de arquivos de origem e destino como locais, de modo que desabilita seu algoritmo delta. Nesse ponto, você quase pode usar cp -p. Veja a resposta que propõe isso e seus comentários subsequentes.
roaima

Respostas:

50

Como você descobriu, não pode usar o rsync com uma fonte remota e um destino remoto. Supondo que os dois servidores não possam conversar diretamente entre si, é possível usar o ssh para fazer um túnel através da sua máquina local.

Ao invés de

rsync -vuar host1:/var/www host2:/var/www

você pode usar isso

ssh -R localhost:50000:host2:22 host1 'rsync -e "ssh -p 50000" -vuar /var/www localhost:/var/www'

Caso você esteja se perguntando, a -Ropção configura um canal reverso da porta 50000 no host1 que mapeia (via sua máquina local) para a porta 22 no host2. Não há conexão direta do host1 para o host2.

roaima
fonte
11
Gosto da solução da @ roaima, mas não consegui fazê-la funcionar por várias razões. No final, eu costumava sshfsmontar os dois diretórios remotos localmente, depois os usava rsyncnos dois diretórios montados localmente.
Aidan
É possível ver um exemplo em que uma chave é usada? Problemas para descobrir como usar -ipara especificar as chaves necessárias para os comandos ssh.
Onassar 31/03
@onassar adiciona o -i key...parâmetro dentro das aspas após o sshcomando. Se isso não ajudar, por favor, sinta-se à vontade para fazer uma nova pergunta, referenciando esta resposta para contexto
roaima 31/03/16
11
a conexão reversa não lê o ~ / .ssh / config no lado local - precisa usar algo que pode ser resolvido como se não houvesse nenhum arquivo SSH configuração
Florenz Kley
11
'Supondo que os dois servidores não possam falar diretamente um com o outro'. Esta solução soluciona um problema de firewall ou NAT que impede uma conexão SSH direta . No entanto, ele não aborda o caso em que, por razões de segurança, o usuário de origem (no host1) não possui chave ou credenciais ou permissões de gravação insuficientes no destino. Para isso, veja a solução de Kevin Cox, ou recorra a uma conexão indireta usando um script ou scp -3.
Cedric Knight
22

Você não disse por que não queria entrar em um host e depois copiar para o outro, para compartilhar uma das minhas razões e soluções.

Não pude fazer login em uma máquina e depois sincronizá-la com a outra porque nenhum host tinha uma chave SSH que poderia se conectar à outra. Resolvi isso usando o encaminhamento de agente SSH para permitir que o primeiro host usasse minha chave SSH enquanto estava conectado.

AVISO: O encaminhamento de SSH permite que o host use sua chave SSH durante o login. Enquanto eles não podem copiar sua chave, eles podem fazer login em outras máquinas com ela. Compreenda os riscos e não use o encaminhamento de agentes em máquinas nas quais não confia.

O comando a seguir usará o encaminhamento do agente SSH para abrir uma conexão direta de host1para host2. Isso tem a vantagem de que a máquina que executa o comando não está afunilando a transferência.

ssh -A host1 rsync -vuar /var/www host2:/var/www
Kevin Cox
fonte
3
+1 para explicar um caso de uso válido (em que o usuário remoto no host1 não tem permissões no servidor de destino); pela importante advertência de segurança (use o encaminhamento de porta em -Dvez de -Acontornar a rede em vez das principais restrições); por explicar a vantagem; para o comando ser curto; e realmente funciona. Observe que você pode precisar especificar username@host1se é diferente do nome de usuário local. Além disso, o rsync executa a verificação da chave do host ao se conectar ao host2, portanto, a chave do host1 já deve estar em ~ / .ssh / known_hosts no host2 ou o comando falhará.
Cedric Cavaleiro
Resposta fenomenal, este me ajudou a orquestrar algumas coisas em TeamCity que eu não era capaz de fazer antes (nb para outros usuários TeamCity, você deve adicionar o "Build Característica" chamado "agente SSH" para sua configuração construção antes de usar ssh -A, consulte confluência. jetbrains.com/display/TCD10/SSH+Agent ).
precisa saber é o seguinte
12

Gosto da resposta de roaima, mas os caminhos são os mesmos nos dois exemplos, obscurecendo qual é qual. Estabelecemos que o seguinte não funciona:

rsync -vuar host1:/host1/path host2:/host2/path

Mas isso acontece (eu omiti o endereço bind_ex explícito do localhost da -Ropção, pois esse é o padrão):

ssh -R 50000:host2:22 host1 'rsync -e "ssh -p 50000" -vuar /host1/path localhost:/host2/path'

Observe que você precisará ter as chaves ssh configuradas corretamente entre os dois hosts remotos, com a chave privada no host1 e a chave pública no host2.

Para depurar a conexão, divida-o em duas partes e adicione o status detalhado:

localhost$ ssh -v -R 50000:host2:22 host1

Se isso funcionar, você terá um shell no host1. Agora tente o comando rsync do host1. Eu recomendo fazer isso em uma janela diferente para que as informações ssh detalhadas não sejam misturadas às informações de status do rsync:

host1$ rsync -e "ssh -p 50000" -vuar /host1/path localhost:/host2/path
jaybrau
fonte
No meu exemplo, os caminhos são origem, destino. O rsyncé iniciado no host1 com o destino no host2. (Você poderia ter pedido esclarecimentos em um comentário.)
roaima
11
Eu teria comentado, mas você não pode comentar na postagem de outra pessoa sem uma reputação de mais de 50 anos.
Jaybrau
7

Reformatando a resposta por roaima na sintaxe do script bash (e adicionando caracteres de continuação de linha '\' para maior clareza), escolhi aleatoriamente a porta 22000 ...

SOURCE_USER=user1
SOURCE_HOST=hostname1
SOURCE_PATH=path1

TARGET_USER=user2
TARGET_HOST=host2
TARGET_PATH=path2

ssh -l $TARGET_USER -A -R localhost:22000:$TARGET_HOST:22 \
$SOURCE_USER@$SOURCE_HOST "rsync -e 'ssh -p 22000' -vuar $SOURCE_PATH \
$TARGET_USER@localhost:$TARGET_PATH"
David I.
fonte
11
parece-me que tudo o que você fez foi substituir os nomes de host arbitrários por variáveis?
Jeff Schaller
3
Sim eu fiz. Isso me esclarece qual é a máquina de origem, qual é o destino e para onde vão os caminhos de origem e destino. Levei um tempo para resolver tudo isso e não era óbvio a partir de simples nomes de host de espaços reservados.
David I.
Da próxima vez, sinta-se à vontade para melhorar a resposta de outra pessoa diretamente, editando-a.
roaima
Esta resposta foi a solução para mim, pois combina o encaminhamento ssh-agent (-A) com o túnel reverso (-R).
camelthemammel
3

A maneira ideal seria executar o rsyncem um desses servidores. Mas se você não deseja executar um script no servidor remoto. Você pode executar um script em seu sistema local, executar um ssh e executar o rsync lá.

ssh user@$host1 <<ENDSSH >> /tmp/rsync.out 2>&1 rsync -vuar /var/www host2:/var/www ENDSSH

Além disso, como você deve saber, o rysnc faz a sincronização unidirecional. Se você quiser uma sincronização bidirecional, consulte o osync ( https://github.com/deajan/osync ). Eu o uso e achei útil.

rahul
fonte
0

Apenas como uma informação adicional:

Se você usa um host de salto para conectar as outras duas máquinas, mas elas não podem se alcançar diretamente, é possível usar o sshfs como meio entre essas duas máquinas (no host de salto):

$ mkdir ~/sourcepath ~/destpath
$ sshfs sourcehost:/target/dir ~/sourcepath
$ sshfs desthost:/target/dir ~/destpath
$ rsync -vua ~/sourcepath ~/desthpath

O SSHFS fornece os dois caminhos no host de salto e o rsync gerencia a sincronização dos arquivos como sempre (apenas com a diferença de que ele é feito virtualmente localmente).

Roger Lehmann
fonte
11
Observe que o desempenho será terrível. Isso ocorre porque, para detectar alterações, o rsync lê o arquivo do servidor de origem, transferindo tudo pela rede. Dito isto, se você não puder fazer uma transferência direta, precisará comer isso se estiver usando o rsync. Também não monte o destino, ele é desnecessário e fará com que o rsync altere alguns padrões, porque pensa que está falando com um disco local.
Kevin Cox
0

Você pode executar um rsyncd (servidor) em um dos computadores.

Esta é a abordagem que estou adotando, já que não quero usar o ssh para permitir que a 'fonte' (no texto do rsync) acesse o 'destino' como raiz sem uma senha (como é necessário para usar o encapsulamento SSH com o rsync no um roteiro)

No meu caso, simplesmente configurei um servidor rsyncd no computador de destino com um único usuário permitido no PC de origem e usei o rsync do lado da fonte.

Funciona bem.

RustyCar
fonte
0

Tente usar isso. Funciona para mim.

ssh src_user@src_host 'rsync -av /src/dir/location/ dest_user@dest_host:/dest/dir/loc/'
Nikhil Pandey
fonte
0

Um script fácil de usar

Ao longo dos anos, eu fiz isso muitas vezes com mais ou menos os mesmos truques de todas as outras respostas aqui. No entanto, como é muito fácil obter alguns detalhes errados e gastar muito tempo descobrindo o problema, vim com o script abaixo:

  1. Facilita a especificação de todos os detalhes (origem, destino, opções)
  2. Testa incrementalmente cada etapa e fornece feedback se algo der errado, para que você saiba o que corrigir.
  3. Solução para os casos em que ssh -Afalha na propagação dos dados de autenticação (não sei por que isso acontece algumas vezes, pois a solução alternativa foi mais fácil do que encontrar a causa raiz)
  4. Finalmente faz o trabalho.

Como usar o script

  1. Certifique-se de poder ssh para os dois hosts do host local sem digitar uma senha.
  2. Defina as variáveis ​​nas primeiras linhas do script
  3. Execute.

Como funciona

Como eu disse, ele usa os mesmos truques que em todas as outras respostas aqui:

  • A -Ropção do ssh para ssh do host local para o host1 e, ao mesmo tempo, configura um encaminhamento de porta que permite ao host1 se conectar via host local ao host2 ( -R localhost:$FREE_PORT:$TARGET_ADDR_PORT)
  • -Aopção do ssh para permitir fácil autenticação do segundo canal ssh

Meu isso é complicado! Existe alguma maneira mais fácil?

Ao copiar todos ou a maioria dos bytes da origem para o destino, é MUITO mais fácil de usar tar:

ssh $SOURCE_HOST "tar czf - $SOURCE_PATH" \
    | ssh $TARGET_HOST "tar xzf - -C $TARGET_PATH/"

O script

#!/bin/bash
#-------------------SET EVERYTHING BELOW-------------------
# whatever you type after ssh to connect to SOURCE/TARGE host 
# (e.g. 1.2.3.4:22, user@host:22000, ssh_config_alias, etc)
# So if you use "ssh foo" to connect to SOURCE then 
# you must set SOURCE_HOST=foo
SOURCE_HOST=host1 
TARGET_HOST=host2 
# The IP address or hostname and ssh port of TARGET AS SEEN FROM LOCALHOST
# So if ssh -p 5678 [email protected] will connect you to TARGET then
# you must set TARGET_ADDR_PORT=1.2.3.4:5678 and
# you must set TARGET_USER=someuser
TARGET_ADDR_PORT=1.2.3.4:5678
TARGET_USER=someuser

SOURCE_PATH=/mnt/foo  # Path to rsync FROM
TARGET_PATH=/mnt/bar  # Path to rsync TO

RSYNC_OPTS="-av --bwlimit=14M --progress" # rsync options
FREE_PORT=54321 # just a free TCP port on localhost
#---------------------------------------------------------

echo -n "Test: ssh to $TARGET_HOST: "
ssh $TARGET_HOST echo PASSED| grep PASSED || exit 2

echo -n "Test: ssh to $SOURCE_HOST: "
ssh $SOURCE_HOST echo PASSED| grep PASSED || exit 3

echo -n "Verifying path in $SOURCE_HOST "
ssh $SOURCE_HOST stat $SOURCE_PATH | grep "File:" || exit 5

echo -n "Verifying path in $TARGET_HOST "
ssh $TARGET_HOST stat $TARGET_PATH | grep "File:" || exit 5

echo "configuring ssh from $SOURCE_HOST to $TARGET_HOST via locahost"
ssh $SOURCE_HOST "echo \"Host tmpsshrs; ControlMaster auto; ControlPath /tmp/%u_%r@%h:%p; hostname localhost; port $FREE_PORT; user $TARGET_USER\" | tr ';' '\n'  > /tmp/tmpsshrs"

# The ssh options that will setup the tunnel
TUNNEL="-R localhost:$FREE_PORT:$TARGET_ADDR_PORT"

echo 
echo -n "Test: ssh to $SOURCE_HOST then to $TARGET_HOST: "
if ! ssh -A $TUNNEL $SOURCE_HOST "ssh -A -F /tmp/tmpsshrs tmpsshrs echo PASSED" | grep PASSED ; then
        echo
        echo "Direct authentication failed, will use plan #B:"
        echo "Please open another terminal, execute the following command"
        echo "and leave the session running until rsync finishes"
        echo "(if you're asked for password use the one for $TARGET_USER@$TARGET_HOST)"
        echo "   ssh -t -A $TUNNEL $SOURCE_HOST ssh -F /tmp/tmpsshrs tmpsshrs"
        read -p "Press [Enter] when done..."
fi

echo "Starting rsync"
ssh -A $TUNNEL $SOURCE_HOST "rsync -e 'ssh -F /tmp/tmpsshrs' $RSYNC_OPTS $SOURCE_PATH tmpsshrs:$TARGET_PATH"

echo
echo "Cleaning up"
ssh $SOURCE_HOST "rm /tmp/tmpsshrs"
ndemou
fonte
taré ótimo quando você tem uma única transferência (não incremental) e sua transferência é concluída em uma única passagem. Por outro lado, rsynccom alças de encaminhamento reinicia e transferências incrementais.
roaima 4/04
11
Claro que @roaima - não considero o alcatrão equivalente. Deixei essa referência de passagem para o dia em que estarei lendo isso para resolver um problema em que o rsync não será 100% necessário.
ndemou 04/04
-1

É possível usar tarvia sshpara transferir os arquivos:

ssh -n user1@host1 'tar jcf - -C /var/www .' | ssh user2@host2 'tar jxvf - -C /var/www'

Altere o jparâmetro (for tar) para zem dois lugares se desejar compactar o arquivo morto em gzipvez de bzip2. Geralmente bzip2tem uma compactação mais alta que gzip, mas é mais lenta, portanto altere-a de acordo com suas necessidades (consulte: bzip2 vs gzip ).

Relacionado: Como copiar entre dois hosts remotos usando o tar canalizado no SSH do servidor remoto quando atrás de um firewall?


Como alternativa (para proteger a largura de banda, devido à compactação transparente), é possível usar sshfspara montar o sistema de arquivos remoto como local e usar rsynccomo de costume, por exemplo,

$ sshfs user1@host1:/var/www /mnt
$ rsync -vuar /mnt user2@host2:/var/www
kenorb
fonte
11
Montar o sistema de arquivos localmente não economizará largura de banda entre a máquina de origem e o local. Ele irá no entanto economizar largura de banda entre o local eo destino (como ele não está montado localmente). Usar o rsync dessa maneira só faz sentido se você estiver tentando economizar largura de banda no destino.
Kevin Cox