rsync hack, aby odbić pliki między dwoma niepołączonymi serwerami

8

Oto połączenie:

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

Serwer 1 i serwer 2 nie mogą rozmawiać bezpośrednio ze sobą (nie pytaj). Mój pulpit jest jednak w stanie uzyskać dostęp do obu serwerów za pośrednictwem ssh.

Muszę skopiować pliki z serwera serwer1 na serwer serwer2.

Tradycyjnie używam hacka ssh + tar, jako takiego:

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

I to działa świetnie, ale chciałbym pójść o krok dalej i uruchomić rsync między dwoma serwerami VIA na moim pulpicie.

Teraz wiem, że mógłbym uruchomić tunel przekierowania portów ssh w jednym terminalu, a następnie rsync nad tym tunelem w innym oknie, ale nie chcę się przejmować drugim terminalem ani tworzyć i łamać osobnego tunelu przekierowania portów. czego chcę to:

  • Jedno polecenie liniowej do rsynchronizacji plików z serwera Serwer1 na serwer Serwer 2 za pomocą pulpitu
  • wszystko w JEDNYM wierszu poleceń, jedno okno terminala
  • Chcę, aby tunel przekierowania portów istniał tylko przez całe życie komendy rsync.
  • Nie chcę scp, chcę rsync.

Czy ktoś ma na to sposób?

EDYCJA: Oto działające polecenie! Świetna robota dla wszystkich: 1. Dla ścieżki klucza rsa, nie można używać tyldy, musiałem użyć „/ root /”. 2. Oto końcowy wiersz poleceń:

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"

Bum przechodzi w dynamit.

regulatre
źródło
To jest naprawdę doskonałe. Jedyną rzeczą, którą należy zmienić, jest wyłączenie weryfikacji klucza hosta. Masz klucz SSH do uwierzytelniania TTYless, ale ponieważ serwery nigdy się ze sobą nie rozmawiały, nie mogą zweryfikować kluczy hosta. Dlatego najlepiej go wyłączyć: -o StrictHostKeyChecking = no po flagach -p lub -i.
Amala

Odpowiedzi:

5

Jeśli z przyjemnością przechowujesz kopię danych na komputerze pośrednim, możesz po prostu napisać skrypt, który zaktualizował kopię lokalną, używając serwera server1 jako referencji, a następnie zaktualizował kopię zapasową na serwerze2, używając kopii lokalnej jako referencji:

#!/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

Użycie prostego skryptu oznacza, że ​​chcesz, aby pojedyncze polecenie wykonało wszystko. Może to być oczywiście nie-bezpieczeństwo, jeśli dane są wrażliwe (ty lub inni w twojej firmie, nie chcesz, aby kopia unosiła się na twoim laptopie). Jeśli serwer1 jest lokalny dla Ciebie, możesz po prostu usunąć lokalną kopię później (ponieważ następnym razem będzie można szybko zrekonstruować lokalną sieć LAN).

Konstrukcja tunelu, aby serwery mogły efektywniej ze sobą rozmawiać, powinna być możliwa w następujący sposób:

  1. Na serwerze 2 wykonaj kopię / bin / sh jako / usr / local / bin / shforkeepalive. Zamiast tego używaj dowiązania symbolicznego, a nie jego kopii; nie musisz jej aktualizować po aktualizacjach bezpieczeństwa łatki / bin / sh.
  2. Na serwerze 2 utwórz skrypt, który przez kilka sekund nie wykonuje nic poza uśpieniem w pętli, a następnie wyśle ​​echo niewielkiej ilości tekstu i użyj tej „kopii” sh:

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

    ( echoprawdopodobnie nie jest to konieczne, ponieważ sesja nie będzie bezczynna przez wystarczająco długi czas, aby przekroczyć limit czasu, nawet jeśli SSHd jest skonfigurowany do ignorowania pakietów utrzymywania aktywności od klienta ssh)

  3. Teraz możesz napisać skrypt na swoim laptopie, który uruchamia tunel zwrotny w tle, informuje serwer server1, aby użył rsync do wykonania operacji kopiowania, a następnie zabija tunel zwrotny, zabijając skrypt zapętlający (który zamyka sesję 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
    

Sposób, w jaki to działa:

  • Wiersz 1: standardowe polecenie „do interpretacji tego skryptu”
  • Wiersz 2: uruchom połączenie SSH z tunelem zwrotnym i uruchom przez niego skrypt podtrzymujący, aby był otwarty. Trailing & mówi bashowi, aby uruchomił to w tle, aby kolejne linie mogły działać bez czekania na zakończenie
  • Wiersz 3: uruchom tunel, który połączy się z tunelem powyżej, aby serwer 1 mógł zobaczyć serwer 2, i uruchom rsync, aby wykonać kopiowanie / aktualizację w ramach tego układu
  • Wiersz 4: zabij skrypt utrzymywania aktywności po zakończeniu operacji rsync (a więc powróci drugie wywołanie SSH), co nastąpi i pierwsza sesja ssh.

Nie wydaje się to szczególnie czyste, ale powinno działać. Nie przetestowałem powyższego, więc może być konieczne jego ulepszenie. Uczynienie z polecenia rsync skryptu jednowierszowego na serwerze server1 może pomóc, zmniejszając potrzebę ucieczki znaków takich jak 'w wywoływanym poleceniu ssh.

BTW: mówisz „nie pytaj”, dlaczego dwa serwery nie widzą się bezpośrednio, ale często jest to dobry powód. Mój serwer domowy i serwer, na których przechowywane są jego kopie zapasowe online, nie mogą się ze sobą zalogować (i mają różne hasła + klucze dla wszystkich użytkowników) - oznacza to, że jeśli jeden z dwóch komputerów zostanie zhakowany, nie można go użyć jako łatwej drogi do zhakuj drugą, aby moje kopie zapasowe były bezpieczniejsze (ktoś złośliwie usuwający moje dane z live nie może wykorzystać swojej możliwości aktualizacji kopii zapasowych, aby usunąć te kopie zapasowe, ponieważ nie ma możliwości bezpośredniego dotknięcia głównej witryny kopii zapasowej). Oba serwery mogą się łączyć z serwerem pośrednim gdzie indziej - serwer na żywo jest ustawiony, aby wcześnie rano przesyłać kopie zapasowe (przez rsync) na maszynę pośrednią, a serwer zapasowy jest ustawiony (chwilę później, aby umożliwić wykonanie kroku pierwszego), aby się połączyć i zbieraj aktualizacje (ponownie za pomocą rsyc, a następnie migawki, aby zachować wiele lat tworzenia kopii zapasowych). Ta technika może być użyteczna również w twoich okolicznościach, a jeśli tak, poleciłbym ją jako znacznie czystszy sposób robienia rzeczy.

Edycja: Scalenie mojego hacka z Aaronem, aby uniknąć całego zamieszania z kopiami / bin / sh i oddzielnym skryptem utrzymywania aktywności na serwerze 2, ten skrypt na twoim laptopie powinien wykonać całą robotę:

#!/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'

Podobnie jak powyżej, rsync łączy się z localhost: 2222, który przesyła tunelem do localhost twojego laptopa: 2222, który przesyła przez drugi tunel do localhost server2: 22.

Edycja 2: Jeśli nie masz nic przeciwko serwerowi 1 posiadającemu klucz, który pozwala mu bezpośrednio uwierzytelnić się na serwerze server2 (nawet jeśli nie widzi serwera server2 bez tunelu), możesz dalej uprościć:

#!/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'

gdzie 123.123.123.123 to adres publiczny dla server2, który może być używany jako kopia + wklej jednowarstwowy zamiast skryptu.

David Spillett
źródło
Jest to duża ilość danych (20 + GB) i wolę strumieniować je jednocześnie i odbierać niż przechowywać lokalnie. Chcę przesyłać strumieniowo dane przez komputer bez konieczności przechowywania jakichkolwiek danych. masz rację co do „nie pytaj”, to z ważnego powodu, choć pita.
regulatre
Plesae widzi nowe zmiany w oryginalnym pytaniu
regulatre
Myślę, że moja ostatnia edycja (opublikowana kilka sekund przed twoim komentarzem zgodnie ze znacznikami czasu, więc prawdopodobnie pisaliśmy w tym samym czasie) może dać ci jedną linijkę, której szukasz.
David Spillett
HOORAY !!! To działa! 1. dla klucza rsa, nie można używać tyldy, musiałem użyć „/ root /”. 2. oto ostatni 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"
wiersz
Cześć @David, dzięki za ten świetny hack. Jednak aby go uruchomić, potrzebuję klucza serwera 2 na serwerze 1, używając obu rozwiązań (w pierwszej i drugiej edycji). Myślę, że to normalne (przekierowywanie portów czy nie, serwer 1 wciąż próbuje się uwierzytelnić na serwerze 2), ale piszesz If you don't mind server1 having a key .... Czy możesz mi powiedzieć, czy naprawdę można uniknąć posiadania klucza server2 na serwerze server1?
ssssteffff,
2

Oto kilka metod, które sprawiają, że synchronizacja jest prostą linią, ale wymaga trochę pracy instalacyjnej.

  • Skonfiguruj tunel zwrotny ssh z serwera serwer1 na pulpit (przepraszam, nie mogę powiedzieć .ssh/configinkantacji z czubka głowy). Połącz go z połączeniem z pulpitu do serwera2. Uruchom rsync z serwera server1.

  • Skonfiguruj serwer proxy skarpet (lub serwer proxy HTTP, który akceptuje CONNECT) na pulpicie. Użyj go, aby ustanowić połączenie ssh z server1 do server2. Uruchom rsync z server2.

  • Użyj unison zamiast rsync. Ale przepływ pracy jest inny.

  • Zamontuj katalogi z jednego lub obu serwerów na pulpicie za pomocą sshfs .

Gilles „SO- przestań być zły”
źródło
1

Dlaczego jedna linia? Użyj małego skryptu powłoki:

#!/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, możesz ustawić niższy czas snu; pierwszy sshnie zakończy się, dopóki ktoś będzie korzystał z kanału.

Aaron Digulla
źródło
Jestem prawie pewien, że rsync nie może w ten sposób działać między dwoma zdalnymi serwerami przez SSH (tylko lokalny-> zdalny lub zdalny-> lokalny) - chociaż wasze użycie sleepi trapjest starsze niż metoda „utrzymuj przy życiu i zabij” w mojej odpowiedzi .
David Spillett,
zobacz zmiany w oryginalnym pytaniu.
regulatre
Cholera, masz rację. Niedozwolone jest określenie dwóch hostów jako argumentów polecenia ling. ... hmmm ..
Aaron Digulla
OK, ulepszyłem swoje rozwiązanie. Musisz utworzyć dwa porty do przodu, aby usługa ssh serwera 2 była widoczna na serwerze 1.
Aaron Digulla
Dodaj kilka „;” aby zamienić go w jedno-liniowy. Pomysł jest łatwiejszy do zrozumienia dzięki skryptowi.
Aaron Digulla