通过ssh复制大量的文件

我通过ssh挂载远程服务器(使用sshfs)。 我想从远程服务器复制大量的文件到本地:

cp -rnv /mounted_path/source/* /local_path/destination 

该命令运行不覆盖现有文件的recursion复制。 但是复制过程很慢。 我注意到它不按顺序复制文件。 所以我的问题是:我可以通过打开多个terminal并运行上面的相同命令来加速复制过程? 复制过程足够智能,不会覆盖其他进程复制的文件吗?

回答原来的问题

这里有两件事要讨论。

使用SSHFS

SSHFS使用SSH协议的SFTP“子系统”使远程文件系统看起来就像本地安装一样。

这里需要注意的一点是,SSHFS将低级 系统调用转换为相对高级别的SFTP命令,然后将其转换为SFTP服务器在服务器上执行的系统调用,然后将结果发送回客户端并向后转换。

这个过程有几个缓慢的原因:

  • 对于不同的文件操作有不同的系统调用,并且按照客户端发出的顺序执行。 假设客户端stat(2)是关于一个文件的信息,然后open(2)这个文件然后读取它的数据 – 通过在一行中执行几个read(2)调用,然后close(2)文件,所有这些系统调用都必须被转换为SFTP命令,发送到服务器并在那里处理,并将其结果发送回客户端,并转回。
  • 即使SSHFS似乎实施了某些聪明的攻击,如“预读”(推测读取的数据比客户端要求的更多),但是每个系统调用都会返回到服务器。 也就是说,我们将数据发送到服务器,然后等待它响应,然后处理它的响应。 IIUC,SFTP没有实现“stream水线” – 一种操作模式,我们在命令完成之前发送命令,所以基本上每个系统调用。 尽pipe在某种程度上具有这种处理技术是可能的 ,但是sshfs似乎并没有实现它。

    IOW,客户端机器上的每个系统调用cp都会将其转换为对服务器的请求,然后等待它进行响应,然后接收响应。

多个cp -n进程并行运行

对于是否可以并行地使用多个cp -n进程复制文件的问题的答案取决于几个注意事项。

首先,如果它们都运行在相同的 SSHFS挂载上,那么由于上面解释的原因,由于所有由多个cp发出的系统调用最终将达到相同的SFTP客户端连接并且将被串行化,所以显然没有加速。

其次,在不同的 SSHFS挂载点上运行多个cp -n实例可能是值得的 – 达到networking吞吐量和目标文件系统下介质/介质的I / O吞吐量所提供的限制。 在这种情况下,至关重要的一点是,由于SSHFS不会在服务器上使用任何locking,因此cp -n的不同实例必须在不同的目录层次结构上运行 – 而不是踩在彼此的脚趾上。

不同/更明智的做法

首先,由tarcpio或其他stream式存档器创build的pipe道数据stream远程处理具有以下优点:避免了文件系统操作的所有往返:本地存档器创build与I / O吞吐量一样快的stream源文件系统允许和发送尽可能快的networking允许; 删除归档程序从stream中提取数据,并尽可能快地更新其本地文件系统。 涉及执行基本“命令”的往返行程不包括在内:您只需按照此stream水线中最慢的I / O点一样快地进行; 加快速度根本不可能。

其次,另一个答案build议使用rsync ,你拒绝了这个build议

rsync很慢,因为它必须校验文件。

这是完全错误的。 引用rsync手册页:

-c ,– --checksum

这改变了rsync检查文件是否已经被更改并且需要传输的方式。 如果没有这个选项,rsync使用“快速检查”(默认情况下)检查每个文件的大小和最后一次修改的时间是否匹配发送者和接收者。 此选项将更改此设置,以比较具有匹配大小的每个文件的128位校验和。

-I --ignore-times

通常情况下,rsync将会跳过已经具有相同大小且修改时间戳相同的文件。 此选项会closures此“快速检查”行为,导致所有文件被更新。

--size-only

这修改了rsync的“快速检查”algorithm,用于查找需要传输的文件,将其从缺省的传输文件中更改大小或更改最后修改时间更改为仅查找大小已更改的文件。 在使用另一个镜像系统(可能不完全保留时间戳)后开始使用rsync时,这很有用。

最后

--existing跳过在接收器上创build新文件

--ignore-existing跳过更新接收器上存在的文件

那是,

  • 默认情况下, rsync不会散列文件的内容,以查看文件是否已经更改。
  • 您可以告诉它的行为与cp -n完全相同,也就是说,如果仅仅存在于远程文件上,则可以跳过更新文件。

不,复制过程并不聪明,不会覆盖其他进程复制的文件。 执行多个命令来复制相同的文件/文件夹不是一个好主意。

有时,当源机器和目标机器太远,networking速度太慢时,你不能做太多事情。 这里有一篇文章讨论为什么SSHFS很慢。

我build议使用通过SSH通道传输的tarcpio两个实例,如in

 $ tar -C src/path -cf - . | ssh user@server tar -C dst/path -xf - 

这种方法的优点是,与SSHFS (和SFTP )相比,使用单个数据stream(“你可以在两者之间插入| pv来看看它是如何进行的,如果你想要一些交互性) – 在服务器和客户端之间。

这里至关重要的一点是,SSH不仅仅是“远程login”,很多人都认为它是远程的,而是在将标准I / Ostream连接到本地SSH客户端实例时远程运行任何命令


请注意,如果这种情况发生在受保护的局域网或其他受控环境中,最好是禁用SSH并使用一对ncsocat实例 – 在服务器上侦听并在客户端上发送。 这种方法不会花费CPU周期对数据进行encryption,因此您可能会受到以下三个组件中的任何一个的I / O限制:源FS,networking和目标FS。

我build议你使用带有avP标志的rsync 。 例:

 rsync -avP <Source> <Destination>