rsync hack para devolver arquivos entre dois servidores desconectados

8

Aqui está a conexão:

[Server1] <---> [my desktop] <---> [Server2]

Servidor1 e servidor2 não têm permissão para falar diretamente entre si (não pergunte). Minha área de trabalho, no entanto, é capaz de acessar os dois servidores via ssh.

Preciso copiar arquivos do servidor1 para o servidor2.

Traiditionally eu tenho usado um hack ssh + tar, como tal:

ssh -q root@Server1 'tar -vzc /path/to/files ' | ssh -q root@Server2 'tar -vzx -C /'

E isso funciona muito bem, mas eu gostaria de dar um passo adiante e fazer com que o rsync funcione entre os dois servidores via meu desktop.

Agora eu sei que poderia iniciar um túnel de encaminhamento de porta ssh em um terminal e sincronizar novamente com o túnel em outra janela, mas não quero mexer com um segundo terminal ou criar e quebrar um túnel de encaminhamento de porta separado. o que eu quero é:

  • Um comando de liner para rsync arquivos do Server1 para o server2 via meu desktop
  • tudo em UMA linha de comando, uma janela de terminal
  • Quero que o túnel de encaminhamento de porta exista apenas durante a vida útil do comando rsync.
  • Eu não quero scp, quero rsync.

Alguém tem um truque para fazer isso?

EDIT: Aqui está o comando de trabalho! Bom trabalho a todos: 1. Para o caminho da chave rsa, não é possível usar o tildae, tinha que usar "/ root /". 2. Aqui está a linha de comando final:

ssh -R 2200:SERVER2:22 root@SERVER1 "rsync -e 'ssh -p 2200 -i /root/.ssh/id_rsa_ROOT_ON_SERVER2' --stats --progress -vaz /path/to/big/files root@localhost:/destination/path"

Boom vai a dinamite.

regulador
fonte
Isso é realmente excelente. A única coisa que precisa ser alterada é desativar a verificação da chave do host. Você tem a chave SSH para autenticação sem TTY, mas como os servidores nunca se comunicaram, não podem verificar as chaves do host. Portanto, é melhor desativá-lo: -o StrictHostKeyChecking = no após os sinalizadores -p ou -i.
Amala

Respostas:

5

Se você deseja manter uma cópia dos dados na máquina intermediária, basta escrever um script que atualize a cópia local usando o server1 como referência e atualize o backup no servidor2 usando a cópia local como referência:

#!/bin/sh
rsync user@server1:/path/to/stuff /path/to/loca/copy -a --delete --compress
rsync /path/to/loca/copy user@server2:/path/to/where/stuff/should/go -a --delete --compress

Usar um script simples significa que ele desejou um único comando para fazer tudo. É claro que isso pode ser um problema de segurança, se os dados forem sensíveis (você ou outras pessoas da sua empresa talvez não desejem uma cópia flutuando no laptop). Se server1 for local para você, você poderá excluir a cópia local posteriormente (pois será rápida a reconstrução na LAN local na próxima vez).

Construir um túnel para que os servidores possam conversar efetivamente mais diretamente entre si deve ser possível da seguinte maneira:

  1. No servidor 2, faça uma cópia de / bin / sh como / usr / local / bin / shforkeepalive. Use um link simbólico em vez de uma cópia para não precisar atualizá-lo após a atualização de segurança desse patch / bin / sh.
  2. No servidor 2, crie um script que não faça nada além de fazer um loop em suspensão por alguns segundos e, em seguida, fazer eco de uma pequena quantidade de texto, e faça com que isso use a agora "cópia" de sh:

    #!/usr/local/bin/shforkeepalive
    while [ "1" != "0" ]; do
            echo Beep!
            sleep 5
    done
    

    ( echoprovavelmente não é necessário, pois a sessão não ficará inativa por tempo suficiente, mesmo que o SSHd esteja configurado para ignorar pacotes keep-alive do cliente ssh)

  3. Agora você pode escrever um script no seu laptop que inicie o seu túnel reverso em segundo plano, diga ao server1 para usar o rsync para executar a operação de cópia e, em seguida, elimine o túnel reverso matando o script em loop (que fechará a sessão SSH):

    #!/bin/sh
    ssh user@server2 -L2222:127.0.0.1:22 /usr/local/bin/keepalivesctipt &
    ssh user@server1 -R2222:127.0.0.1:2222 rsync /path/to/stuff [email protected]:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'
    ssh user@server2 killall shforkeepalive
    

Como isso funciona:

  • Linha 1: marcador "comando a ser usado para interpretar esse script" padrão
  • Linha 2: inicie uma conexão SSH com túnel reverso e execute o script keepalive por meio dele para mantê-lo aberto. O trailing & diz ao bash para executar isso em segundo plano, para que as próximas linhas possam ser executadas sem esperar pela conclusão
  • Linha 3: inicie um túnel que se conectará ao túnel acima para que o servidor1 possa ver o servidor2 e execute o rsync para executar a cópia / atualização sobre esse arranjo
  • Linha 4: interrompa o script keep-alive assim que a operação rsync for concluída (e a segunda chamada SSH retornar), o que ocorrerá e a primeira sessão ssh.

Isso não parece particularmente limpo, mas deve funcionar. Eu não testei o acima, então você pode precisar ajustá-lo. Tornar o comando rsync um script de linha única no servidor1 pode ajudar a reduzir qualquer necessidade de escapar caracteres como o 'no comando de chamada ssh.

BTW: você diz "não pergunte" por que os dois servidores não podem se ver diretamente, mas geralmente há uma boa razão para isso. Meu servidor doméstico e o servidor em que seus backups on-line são mantidos não podem se conectar (e possuem senhas + chaves diferentes para todos os usuários) - isso significa que, se um dos dois for invadido, ele não poderá ser usado como uma rota fácil para hackear o outro para que meus backups on-line sejam mais seguros (alguém que deleta meus dados do Live não pode usar sua capacidade de atualizar os backups para excluir os backups, pois não tem capacidade direta de tocar no site principal de backup). Ambos os servidores podem se conectar a um servidor intermediário em outro local - o servidor ativo está configurado para enviar seus backups (via rsync) para a máquina intermediária no início da manhã e o servidor de backup está configurado (um pouco mais tarde para permitir que a etapa 1 seja concluída) para se conectar e colete as atualizações (novamente via rsyc, seguidas de uma etapa de captura instantânea para manter várias idades de backup). Essa técnica também pode ser utilizável em sua circunstância e, nesse caso, eu a recomendaria como uma maneira muito mais limpa de fazer as coisas.

Edit: Mesclando meu hack com o Aaron para evitar toda a confusão com cópias de / bin / sh e um script keep-alive separado no server2, esse script no seu laptop deve fazer todo o trabalho:

#!/bin/sh
ssh user@server2 -L2222:127.0.0.1:22 sleep 60 &
pid=$!
trap "kill $pid" EXIT 
ssh user@server1 -R2222:127.0.0.1:2222 rsync /path/to/stuff [email protected]:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'

Como acima, o rsync está se conectando ao localhost: 2222, que encaminha o túnel ao localhost do seu laptop: 2222, que encaminha o outro túnel ao localhost do servidor2: 22.

Edit 2: Se você não se importa com o server1 com uma chave que permita a autenticação direta com o server2 (mesmo que não consiga ver o server2 sem um túnel), você pode simplificar ainda mais com:

#!/bin/sh
ssh user@server1 -R2222:123.123.123:22 rsync /path/to/stuff [email protected]:/destination/path/to/update -a --delete --compress -e 'ssh -p 2222'

em que 123.123.123.123 é um endereço público do servidor2, que pode ser usado como copiar + colar uma linha em vez de um script.

David Spillett
fonte
É uma grande quantidade de dados (20 + gb) e eu prefiro transmiti-los ao mesmo tempo, em vez de armazená-los localmente. Desejo transmitir os dados pelo meu PC sem que nada seja armazenado. você está certo sobre o "não pergunte", é por uma boa razão, embora seja uma pita.
regulatre
Plesae vê novas edições na pergunta original
regulatre
Acho que minha última edição (postada segundos antes do seu comentário de acordo com os carimbos de data e hora, portanto provavelmente estávamos digitando ao mesmo tempo) pode fornecer a única linha que você está procurando.
David Spillett
HOORAY !!! Funciona! 1. para chave rsa, não pode usar tildae, tinha que usar "/ root /". 2. aqui está a linha de comando final:ssh -R 2200:SERVER2:22 root@SERVER1 "rsync -e 'ssh -p 2200 -i /root/.ssh/id_rsa_ROOT_ON_SERVER2' --stats --progress -vaz /path/to/big/files root@localhost:/destination/path"
regulatre 25/08/10
Oi @ David, obrigado por este ótimo hack. No entanto, para fazê-lo funcionar, preciso da chave do servidor 2 no servidor 1 usando as duas soluções (na primeira e na segunda edições). Eu acho que é normal (encaminhamento de porta ou não, server1 ainda está tentando se autenticar no server2), mas você escreve If you don't mind server1 having a key .... Você pode me dizer se é realmente possível evitar ter a chave do server2 no server1, por favor?
ssssteffff
2

Aqui estão alguns métodos que tornam a sincronização uma linha única, mas requerem algum trabalho de configuração.

  • Configure um túnel ssh reverso do server1 para a sua área de trabalho (desculpe, não posso lhe dizer o .ssh/configencantamento do topo da minha cabeça). Encadeie-o com uma conexão da área de trabalho ao servidor2. Execute o rsync no server1.

  • Configure um proxy de meias (ou um proxy http que aceite CONNECT) na área de trabalho. Use-o para estabelecer uma conexão ssh do servidor1 para o servidor2. Execute o rsync no servidor2.

  • Use uníssono em vez de rsync. Mas o fluxo de trabalho é diferente.

  • Monte os diretórios de um ou dos dois servidores na área de trabalho usando sshfs .

Gilles 'SO- parar de ser mau'
fonte
1

Por que uma linha? Use um pequeno script de shell:

#!/bin/bash
# Run me on server1

# Create the port forward server1 -> desktop -> server2 (i.e.
# the first forward creates a second tunnel running on the desktop)
ssh -L/-R ... desktop "ssh -L/-R ... server2 sleep 1h" &    
pid=$!

# Kill port forward process on exit and any error
trap "kill $pid" EXIT 

rsync -e ssh /path/to/files/ root@localhost:/path/to/files/on/server2

IIRC, você pode definir o tempo de sono mais baixo; o primeiro sshnão terminará enquanto alguém usar o canal.

Aaron Digulla
fonte
Tenho certeza de que o rsync não pode operar entre dois servidores remotos através do SSH dessa maneira (apenas local-> remoto ou remoto-> local) - embora o uso sleepe a traplimpeza sejam mais agradáveis ​​do que o método "manter vivo e matar" na minha resposta .
precisa saber é o seguinte
consulte as edições na pergunta original.
regulatre 23/08/10
Porra, você está certo. Não é permitido especificar dois hosts como argumentos no comando ling. ... hmmm ..
Aaron Digulla
Ok, eu melhorei minha solução. Você precisa criar duas portas para a frente para tornar o serviço ssh do server2 visível no server1.
Aaron Digulla 23/08/10
Adicione um par de ";" para transformá-lo em uma linha. A ideia é mais fácil de entender com um script.
Aaron Digulla 23/08/10