我想使用rsync和SSH(来自Python程序)从远程计算机获取文件。
如何启动rsync的本地实例并将其引入我使用Paramiko打开的SSH通道?
答案 0 :(得分:6)
这是一个老问题,但仍然是谷歌在搜索“rsram over paramiko”时的第一次打击,而这里唯一的投票项目是与OP的问题无关的评论(该评论中的链接指向使用Paramiko不支持的ControlMaster。
有一个如何在Paramiko演示here之一中设置本地端口转发的示例。在pull request中还有一个更易于使用的版本。您可以通过两种方式使用本地端口转发:
rsync
。这相当于运行ssh -L12345:localhost:22 remote-host
后跟rsync --rsh 'ssh -p 12345' sourcedir/file localhost:/destdir/file
。rsync
。这类似于运行ssh -L12345:localhost:12345
后跟rsync sourcedir/file rsync://localhost:12345/module/destdir/file
,除了您需要在12345
上运行的ad-hoc rsync守护程序,其模块名称指向destdir
在远程主机上。我个人更喜欢上面的第二种方法,虽然它稍微复杂一点,因为它会跳过本地ssh
客户端并使用rsync协议,我认为它比使用ssh
更有效。
使用上述拉取请求中的ForwardServer
,代码看起来有点像这样(取决于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))
您还可以使该函数采用远程绝对路径并生成模块的目录(而不是假设它相对于用户的主目录)。
答案 1 :(得分:0)
我遇到了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中使用它是否有问题,或者我只是坚持不够长。