2013-05-11 9 views
5

Vorrei ottenere file da una macchina remota usando rsync e SSH (da un programma Python).rsync su ssh - utilizzando il canale creato da Paramiko in Python

Come si avvia un'istanza locale di rsync e la si introduce nel canale SSH che ho aperto con Paramiko?

+0

Buon inizio da qui credo: http://unix.stackexchange.com/questions/48632/cant-share-an-ssh-connection-with-rsync –

+0

Avete veramente bisogno di rsync? Ho implementato un semplice rimpiazzo per ciò che controlla l'ora di modifica su SFTP e carica il file se il tuo host ha un file più recente: https://github.com/myaut/tsload/blob/master/agent/tools/buildsvc.py#L17 – myaut

risposta

0

Ho avuto problemi con paramiko e rsync che non ero in grado di risolvere. Io abitualmente uso paramiko con successo con un numero di altri comandi (ad esempio, mkdir, mpstat, servizi, programmi Python locali, ecc), utilizzando questo quadro tipico:

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 

Per quanto riguarda rsync, piuttosto che perseguire una soluzione di paramiko, sono ritornato a:

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

io generalmente preferisco paramiko perché è facile per elaborare le sue uscite, quindi mi sarebbe interessato a sapere se c'è un problema di utilizzarlo con rsync o io non ho persistere abbastanza a lungo.

3

Questa è una vecchia domanda, ma è ancora il primo successo in Google durante la ricerca di "rsync su paramiko", e l'unico elemento sopra votato qui è un commento che non è correlato alla domanda dell'OP (il link in quel commento punti usare ControlMaster che non è supportato da Paramiko).

C'è un esempio di come configurare il port forwarding locale in una delle demo di Paramiko here. C'è anche una versione più semplice di esso in uno pull request. È possibile utilizzare l'inoltro di porta locale in due modi:

  1. avanti una porta locale ad-hoc per il server SSH remoto e rsync sulla porta locale utilizzando il protocollo SSH. Questo equivale all'esecuzione di ssh -L12345:localhost:22 remote-host seguito da rsync --rsh 'ssh -p 12345' sourcedir/file localhost:/destdir/file.
  2. Inoltra una porta locale ad-hoc a un daemon rsync remoto ad-hoc e rsync sulla porta locale utilizzando il protocollo rsync. È simile all'esecuzione di ssh -L12345:localhost:12345 seguito da rsync sourcedir/file rsync://localhost:12345/module/destdir/file, con la differenza che è necessario configurare un daemon rsync ad hoc in esecuzione su 12345 con un nome modulo che punta allo destdir sull'host remoto.

Io personalmente preferisco il secondo approccio di cui sopra, anche se è un po 'più complessa perché, salta il client locale ssh e utilizza anche il protocollo rsync che credo sia più efficiente rispetto all'utilizzo ssh.

Utilizzando la ForwardServer dalla richiesta di pull sopra, il codice sarà un po 'come questo (dipende 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)) 

Si può avere anche la funzione di prendere un percorso remoto assoluto e generare la directory per il modulo (invece di assumere che sia relativo alla home directory dell'utente).

Problemi correlati