2013-05-11 13 views
5

Chciałbym uzyskać pliki z komputera zdalnego za pomocą rsync i SSH (z poziomu programu Python).rsync przez ssh - używając kanału utworzonego przez Paramiko w Pythonie

Jak uruchomić lokalną instancję rsync i wprowadzić ją do kanału SSH, który otworzyłem z Paramiko?

+0

Dobry początek stąd wierzę: http://unix.stackexchange.com/questions/48632/cant-share-an-ssh-connection-with-rsync –

+0

Czy naprawdę potrzebujemy rsync? Wprowadziłem prosty zamiennik dla tego, który sprawdza czas modyfikacji przez SFTP i przesyła plik, jeśli twój host ma nowszy plik: https://github.com/myaut/tsload/blob/master/agent/tools/buildsvc.py#L17 – myaut

Odpowiedz

0

Miałem problemy z paramiko i rsync, których nie byłem w stanie opracować. I rutynowo używać paramiko powodzeniem Szereg innych poleceń (np mkdir, mpstat, usług, programów lokalnych Python, etc), przy użyciu tej typowej ramy:

client = paramiko.SSHClient() 
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
    client.connect(domain, username="root",timeout=5) 

    stdin, mpstat, stderr = client.exec_command('mpstat') 
    x=mpstat.readlines() 
    # process the lines as though it is a file 

W odniesieniu do rsync, zamiast dążyć do rozwiązania paramiko, I powrócił do:

x='''ssh [email protected]%s "rsync -aRzq [email protected]%s:%s /root/Backups/%s/%s " \ 
     '''%(BackupServerIP, ServerIP, file, Service, Server) 
    os.system(x) 

ja generalnie wolę paramiko ponieważ jest łatwy do przetworzenia jej wyjść, więc chciałbym się dowiedzieć, czy istnieje problem z użyciem rsync lub po prostu nie utrzymują się długo wystarczy.

3

To jest stare pytanie, ale wciąż pierwsze trafienie w Google podczas wyszukiwania "rsync over paramiko", a jedyną pozycją, która została odrzucona w tym miejscu, jest komentarz, który nie jest związany z pytaniem OP (link w tym punkcie komentarza do korzystania z ControlMaster, który nie jest obsługiwany przez Paramiko).

Istnieje przykład konfiguracji lokalnego przekazywania portów w jednym z demonstracji Paramiko here. Dostępna jest również wersja łatwiejsza w użyciu w wersji pull request. Można użyć lokalnej przekierowanie portów na dwa sposoby:

  1. przekazać lokalny port ad-hoc do zdalnego serwera ssh i rsync przez lokalny port za pomocą protokołu SSH. Jest to równoważne uruchomieniu ssh -L12345:localhost:22 remote-host, a następnie rsync --rsh 'ssh -p 12345' sourcedir/file localhost:/destdir/file.
  2. Przekieruj lokalny port ad-hoc do zdalnego demona rsync ad-hoc i rsync przez port lokalny przy użyciu protokołu rsync. Jest to podobne do uruchamiania ssh -L12345:localhost:12345, po którym następuje rsync sourcedir/file rsync://localhost:12345/module/destdir/file, z tym że musisz skonfigurować demona rsync ad-hoc działającego pod numerem 12345 z nazwą modułu, która wskazuje na destdir na zdalnym hoście.

ja osobiście wolę 2nd podejście powyżej, choć jest nieco bardziej skomplikowana, ponieważ pomija lokalną ssh klienta, a także używa protokołu rsync, który moim zdaniem jest bardziej wydajny niż przy użyciu ssh.

Używanie ForwardServer z powyższego wniosek ciągnącej, kod będzie wyglądał mniej więcej tak (zależy Fabric):

RSYNC_SPEC = """ 
port=12345 
use chroot=false 

[homedir] 
log file=/tmp/rsync-ad-hoc.log 
max verbosity=4 
path=/home/{user}/ 
read only=false 
""" 

@task 
def rsync(local_path, remote_path): 
    """ 
    local_path: Absolute path to a local source 
    remote_path: Relative path (from home directory) to a remote destination 
    """ 
    with ForwardServer(0, "localhost", rsync_port, connections[env.host_string].get_transport()) as serv: 
     local_port = serv.socket.getsockname()[1] 
     run("killall rsync; rm -f /tmp/rsync-ad-hoc.log /tmp/rsync-ad-hoc.conf; :") 
     put(local_path=StringIO(RSYNC_SPEC.format(user=env.user)), remote_path="/tmp/rsync-ad-hoc.conf",) 
     run("rsync --daemon --config /tmp/rsync-ad-hoc.conf") 
     remote_rsync_path = os.path.join("rsync://localhost:%s/homedir" % local_port, remote_path) 
     # Rsync expects the root of the destination to exist. 
     run("mkdir -p /home/{user}/{path}".format(user=env.user, path=remote_path)) 
     logging.info("Attempting rsync from (localhost, %s, %s) to (%s, %s, %s)", local_port, local_path, env.host_string, rsync_port, remote_path) 
     local("rsync -avzPh --delete %s/ %s/" % (local_path, remote_rsync_path)) 

Można również funkcja wziąć zdalnego ścieżki bezwzględnej i wygenerować katalog dla moduł (zamiast zakładać, że jest on względny w stosunku do katalogu domowego użytkownika).

Powiązane problemy