ssh上的rsync-使用由Paramiko在Python中创建的通道

ssh上的rsync-使用由Paramiko在Python中创建的通道,python,ssh,rsync,paramiko,Python,Ssh,Rsync,Paramiko,我希望使用rsync和SSH(在Python程序中)从远程机器获取文件 如何启动rsync的本地实例并将其引入我与Paramiko一起打开的SSH通道?我在Paramiko和rsync方面遇到了一些问题,我无法解决这些问题。我经常使用以下典型框架成功地将paramiko与许多其他命令(例如,mkdir、mpstat、service、本地python程序等)结合使用: client = paramiko.SSHClient() client.set_missing_host_key

我希望使用rsync和SSH(在Python程序中)从远程机器获取文件


如何启动rsync的本地实例并将其引入我与Paramiko一起打开的SSH通道?

我在Paramiko和rsync方面遇到了一些问题,我无法解决这些问题。我经常使用以下典型框架成功地将paramiko与许多其他命令(例如,mkdir、mpstat、service、本地python程序等)结合使用:

    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
关于rsync,我没有追求paramiko解决方案,而是转而:

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

我通常更喜欢paramiko,因为它很容易处理输出,所以我想知道在rsync中使用它是否有问题,或者我坚持的时间不够长。

这是一个老问题,但在谷歌搜索“rsync over paramiko”时仍然是第一个热门话题,这里唯一的投票结果是一条与OP的问题无关的评论(该评论中的链接指向使用ControlMaster,这是Paramiko不支持的)

下面是一个如何在其中一个Paramiko演示中设置本地端口转发的示例。还有一个更易于使用的版本。您可以通过两种方式使用本地端口转发:

  • 使用ssh协议通过本地端口将临时本地端口转发到远程ssh服务器和
    rsync
    。这相当于运行
    ssh-L12345:localhost:22 remote host
    ,然后运行
    rsync--rsh'ssh-p 12345'sourcedir/file localhost:/destdir/file
  • 使用rsync协议通过本地端口将临时本地端口转发到临时远程rsync守护程序和
    rsync
    。这类似于运行
    ssh-L12345:localhost:12345
    然后运行
    rsync sourcedir/filersync://localhost:12345/module/destdir/file
    ,但您需要设置一个在
    12345
    上运行的临时rsync守护程序,该守护程序的模块名指向远程主机上的
    destdir
  • 我个人更喜欢上面的第二种方法,尽管它稍微复杂一些,因为它跳过了本地
    ssh
    客户端,还使用rsync协议,我认为这比使用
    ssh
    更有效

    使用上述拉取请求中的
    ForwardServer
    ,代码看起来有点像这样(取决于
    Fabric
    ):


    您还可以让函数获取远程绝对路径并为模块生成目录(而不是假设它相对于用户的主目录)。

    从这里开始,我相信:您真的需要rsync吗?我已经实现了一个简单的替换,它可以检查SFTP上的修改时间,并在您的主机有更新的文件时上载文件:如何将
    rsync
    替换为
    SFTP
    功能?因为,是的,我确实“真的需要”rsync。
    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))