我想在本地外壳上使用两个远程主机之间传输文件,但是如果按如下所示指定两个远程,则rsync似乎不支持同步:
$ rsync -vuar host1:/var/www host2:/var/www
The source and destination cannot both be remote.
我还可以使用其他哪些解决方法/命令来获得相似的结果?
我想在本地外壳上使用两个远程主机之间传输文件,但是如果按如下所示指定两个远程,则rsync似乎不支持同步:
$ rsync -vuar host1:/var/www host2:/var/www
The source and destination cannot both be remote.
我还可以使用其他哪些解决方法/命令来获得相似的结果?
Answers:
如发现的那样,您无法将rsync与远程源和远程目标一起使用。假设两个服务器不能直接相互通信,则可以使用ssh通过本地计算机建立隧道。
代替
rsync -vuar host1:/var/www host2:/var/www
你可以用这个
ssh -R localhost:50000:host2:22 host1 'rsync -e "ssh -p 50000" -vuar /var/www localhost:/var/www'
如果您想知道,该-R
选项设置了从host1上的端口50000反向通道,该通道映射(通过本地计算机)到host2上的端口22。从host1到host2没有直接连接。
sshfs
在本地安装两个远程目录,然后rsync
在两个本地安装的目录中使用。
-i
指定ssh命令所需的键。
-i key...
在ssh
命令后的引号内添加参数。如果那不能解决您的问题,请随时提出一个新问题,并参考上下文的答案
scp -3
。
您没有说为什么不想登录到一台主机然后复制到另一台主机,所以我将分享我的一个原因和解决方案。
我无法登录到一台计算机,然后无法同步到另一台计算机,因为两台主机都没有可以登录另一台计算机的SSH密钥。我通过使用SSH代理转发来解决此问题,从而允许第一台主机在登录时使用我的SSH密钥。
警告: SSH转发允许主机在您登录期间使用SSH密钥。尽管他们无法复制您的密钥,但他们可以使用它登录其他计算机。确保您了解风险,并且不要对不信任的计算机使用代理转发。
以下命令将使用SSH代理转发打开从host1
到的直接连接host2
。这样做的好处是,运行命令的计算机不会阻塞传输。
ssh -A host1 rsync -vuar /var/www host2:/var/www
-D
而不是-A
绕过网络而不是密钥限制);用于解释优势;因为命令很短;它实际上有效。请注意,您可能需要指定username@host1
它是否与本地用户名不同。同样,rsync在连接到host2时会执行主机密钥验证,因此host1的密钥应该已经在host2上的〜/ .ssh / known_hosts中,否则命令将失败。
ssh -A
,在使用之前,必须在构建配置中添加名为“ SSH代理”的“ Build Feature” ,请参见融合)。 jetbrains.com/display/TCD10/SSH+Agent)。
我喜欢roaima的答案,但是两个示例中的路径都相同,但不清楚是哪个。我们确定以下内容不起作用:
rsync -vuar host1:/host1/path host2:/host2/path
但这确实是(我从-R
选项中省略了localhost的显式bind_address,因为这是默认设置):
ssh -R 50000:host2:22 host1 'rsync -e "ssh -p 50000" -vuar /host1/path localhost:/host2/path'
请注意,必须在两个远程主机之间正确设置ssh密钥,其中host1上的私钥和host2上的公钥。
要调试连接,请将其分为两部分并添加详细状态:
localhost$ ssh -v -R 50000:host2:22 host1
如果可行,您将在host1上安装一个shell。现在,尝试从host1执行rsync命令。我建议在其他窗口中执行此操作,以免将冗长的ssh信息与rsync状态信息混合在一起:
host1$ rsync -e "ssh -p 50000" -vuar /host1/path localhost:/host2/path
rsync
是在与主机2目标主机1启动。(您可能已在评论中要求澄清。)
我用bash脚本语法重新格式化了roaima的答案(为清楚起见,并添加了行继续符'\'),我随机选择了端口22000 ...
SOURCE_USER=user1
SOURCE_HOST=hostname1
SOURCE_PATH=path1
TARGET_USER=user2
TARGET_HOST=host2
TARGET_PATH=path2
ssh -l $TARGET_USER -A -R localhost:22000:$TARGET_HOST:22 \
$SOURCE_USER@$SOURCE_HOST "rsync -e 'ssh -p 22000' -vuar $SOURCE_PATH \
$TARGET_USER@localhost:$TARGET_PATH"
理想的方法是rsync
在其中一台服务器上运行。但是,如果您不想在远程服务器上运行脚本。您可以在本地系统上运行脚本并执行ssh并在那里执行rsync。
ssh user@$host1 <<ENDSSH >> /tmp/rsync.out 2>&1
rsync -vuar /var/www host2:/var/www
ENDSSH
另外,您可能已经知道rysnc进行单向同步。如果您想要双向同步,可以查看osync(https://github.com/deajan/osync)。我使用它,发现它很有帮助。
作为附加信息:
如果您使用跳转主机连接其他两台计算机,但它们不能直接相互连接,则可以在这两台计算机之间使用sshfs作为介质,就像这样(在跳转主机上):
$ mkdir ~/sourcepath ~/destpath
$ sshfs sourcehost:/target/dir ~/sourcepath
$ sshfs desthost:/target/dir ~/destpath
$ rsync -vua ~/sourcepath ~/desthpath
SSHFS在跳转主机上提供了两条路径,rsync像往常一样管理文件的同步(只是区别在于它实际上是在本地完成的)。
尝试使用这个。这个对我有用。
ssh src_user@src_host 'rsync -av /src/dir/location/ dest_user@dest_host:/dest/dir/loc/'
易于使用的脚本
多年来,我用与这里其他所有答案差不多的技巧做了很多次。但是,由于很容易弄错一些细节并花费大量时间来解决问题,因此我在下面提供了以下脚本:
ssh -A
无法传播身份验证数据的情况(不知道为什么有时会发生这种情况,因为解决方法比查找根本原因更容易)如何使用脚本
这个怎么运作
正如我所说的,它使用与此处其他所有答案相同的技巧:
-R
从localhost到host1的ssh 选项,同时设置端口转发,然后允许host1通过localhost连接到host2(-R localhost:$FREE_PORT:$TARGET_ADDR_PORT
)-A
选项,可以轻松验证第二个ssh chanel我的这很复杂!有没有更简单的方法?
将所有或大部分字节从源复制到目标时,FAR易于使用tar
:
ssh $SOURCE_HOST "tar czf - $SOURCE_PATH" \
| ssh $TARGET_HOST "tar xzf - -C $TARGET_PATH/"
剧本
#!/bin/bash
#-------------------SET EVERYTHING BELOW-------------------
# whatever you type after ssh to connect to SOURCE/TARGE host
# (e.g. 1.2.3.4:22, user@host:22000, ssh_config_alias, etc)
# So if you use "ssh foo" to connect to SOURCE then
# you must set SOURCE_HOST=foo
SOURCE_HOST=host1
TARGET_HOST=host2
# The IP address or hostname and ssh port of TARGET AS SEEN FROM LOCALHOST
# So if ssh -p 5678 someuser@1.2.3.4 will connect you to TARGET then
# you must set TARGET_ADDR_PORT=1.2.3.4:5678 and
# you must set TARGET_USER=someuser
TARGET_ADDR_PORT=1.2.3.4:5678
TARGET_USER=someuser
SOURCE_PATH=/mnt/foo # Path to rsync FROM
TARGET_PATH=/mnt/bar # Path to rsync TO
RSYNC_OPTS="-av --bwlimit=14M --progress" # rsync options
FREE_PORT=54321 # just a free TCP port on localhost
#---------------------------------------------------------
echo -n "Test: ssh to $TARGET_HOST: "
ssh $TARGET_HOST echo PASSED| grep PASSED || exit 2
echo -n "Test: ssh to $SOURCE_HOST: "
ssh $SOURCE_HOST echo PASSED| grep PASSED || exit 3
echo -n "Verifying path in $SOURCE_HOST "
ssh $SOURCE_HOST stat $SOURCE_PATH | grep "File:" || exit 5
echo -n "Verifying path in $TARGET_HOST "
ssh $TARGET_HOST stat $TARGET_PATH | grep "File:" || exit 5
echo "configuring ssh from $SOURCE_HOST to $TARGET_HOST via locahost"
ssh $SOURCE_HOST "echo \"Host tmpsshrs; ControlMaster auto; ControlPath /tmp/%u_%r@%h:%p; hostname localhost; port $FREE_PORT; user $TARGET_USER\" | tr ';' '\n' > /tmp/tmpsshrs"
# The ssh options that will setup the tunnel
TUNNEL="-R localhost:$FREE_PORT:$TARGET_ADDR_PORT"
echo
echo -n "Test: ssh to $SOURCE_HOST then to $TARGET_HOST: "
if ! ssh -A $TUNNEL $SOURCE_HOST "ssh -A -F /tmp/tmpsshrs tmpsshrs echo PASSED" | grep PASSED ; then
echo
echo "Direct authentication failed, will use plan #B:"
echo "Please open another terminal, execute the following command"
echo "and leave the session running until rsync finishes"
echo "(if you're asked for password use the one for $TARGET_USER@$TARGET_HOST)"
echo " ssh -t -A $TUNNEL $SOURCE_HOST ssh -F /tmp/tmpsshrs tmpsshrs"
read -p "Press [Enter] when done..."
fi
echo "Starting rsync"
ssh -A $TUNNEL $SOURCE_HOST "rsync -e 'ssh -F /tmp/tmpsshrs' $RSYNC_OPTS $SOURCE_PATH tmpsshrs:$TARGET_PATH"
echo
echo "Cleaning up"
ssh $SOURCE_HOST "rm /tmp/tmpsshrs"
tar
当您进行单次(非增量)转移并且一次转移完成转移时,该功能非常有用。另一方面,rsync
带有转发句柄的重新启动和增量传输。
可以使用tar
via ssh
来传输文件:
ssh -n user1@host1 'tar jcf - -C /var/www .' | ssh user2@host2 'tar jxvf - -C /var/www'
如果您想使用而不是压缩档案,请将j
(for tar
)参数z
在两个位置更改。通常压缩率要高于,但速度较慢,因此请根据需要进行更改(请参阅:bzip2 vs gzip)。gzip
bzip2
bzip2
gzip
相关:在防火墙后面时,如何使用从远程服务器通过SSH连接到SSH的tar在两个远程主机之间进行复制?
另外(为了保证带宽,由于透明压缩),可以sshfs
将远程文件系统挂载为本地文件,并rsync
像往常一样使用,例如
$ sshfs user1@host1:/var/www /mnt
$ rsync -vuar /mnt user2@host2:/var/www