我有一个正在部署代码的远程服务器。我目前正在使用scp
上传代码,但scp
速度非常慢,我想切换到rsync
(或其他更有效的东西)。瓶颈在于建立ssh
连接,因此我想尽量减少与服务器建立的连接数量。
在本地,我的构建过程输出一个out
包含bin
,lib
和etc
子目录的目录。我将输出文件的子集推送到远程服务器上的匹配位置。
我的scp
命令如下所示:
scp out/bin/$BINFILES remote:/usr/bin
scp out/lib/$LIBFILES remote:/usr/lib
scp out/etc/$ETCFILES remote:/etc
这将建立与远程服务器的三个连接,并完整复制文件,即使它们没有被修改。这就是我所做的rsync
:
rsync -e ssh -avz out/bin/$BINFILES remote:/usr/bin
rsync -e ssh -avz out/lib/$LIBFILES remote:/usr/lib
rsync -e ssh -avz out/etc/$ETCFILES remote:/etc
它更快(压缩和消除重复项),但仍然与远程服务器建立三个连接。
有没有办法使用单个rsync
命令来实现这三个副本?如果可行的话,我愿意在复制之前将所有 {src,dest} 对放入临时文件中。
我也愿意尝试不同的工具,但它应该适用于 OS X(我当前的开发平台),并且它最好应该支持传输优化rsync
。
答案1
多个连续的 rsync 命令速度慢的原因是建立 SSH 连接需要一些时间。您可以通过以下方式解决这个问题使用已建立的 SSH 通道。设置主连接共享,然后打开一个主连接,不加更改地使用 rsync 命令(请注意,这-e ssh
是十年左右以来的默认命令),最后关闭 SSH 连接:
ssh -Nf remote
rsync -avz out/bin/$BINFILES remote:/usr/bin
rsync -avz out/lib/$LIBFILES remote:/usr/lib
rsync -avz out/etc/$ETCFILES remote:/etc
ssh -O exit remote
如果您无法使用 SSH 连接共享(例如,因为一侧正在运行 Dropbear 或非常旧版本的 OpenSSH),您可以建立隧道,但是这样比较麻烦。
或者,通过一些工作,您可以将 rsync 命令重构为一个,方法是使用rsync过滤器和符号链接。如果您可以移动bin
和lib
目录,那就很容易了:
mkdir out/usr
mv out/bin out/lib out/usr/
rsync -avz \
--include='/bin/***' --include='/lib/***' --include='/etc/***' \
--exclude='*' out/ remote:/
如果您无法移动它们,但您正在复制的树中没有任何绝对符号链接,则可以使用绝对符号链接并告诉 rsync 将其视为目录:
ln -s "$PWD" out/usr
rsync -avz --copy-unsafe-links \
--include='/bin/***' --include='/lib/***' --include='/etc/***' \
--exclude='*' out/ remote:/