如何在部分复制文件的情况下恢复scp?

169

我正在使用scp shell命令复制大量文件夹中的文件。

但是在某个时刻,我不得不终止运行中的命令(通过Ctrl+C或kill)。

据我所知,scp按顺序复制文件,因此应该只有一个部分复制的文件。

如何恢复同一scp命令以不覆盖已成功复制的文件并正确处理部分复制的文件?

P.S. 我知道我可以在rsync中做这种事情,但是由于某些原因,scp对我来说更快,所以我使用它。


4
我猜测 rsync 速度较慢是因为它花费额外的时间来执行一些操作,以便您能够重新启动传输。您可以考虑仅使用 rsync 完成部分传输。 - Keith Thompson
2
如果你想聪明一点,你可以尝试使用适当的“skip”变量来运行dd命令,并将其管道传输到ssh :) - Mark Nunberg
1
这个问题与SO无关,应该发到SuperUser上。实际上,已经有人在那里提出了类似的问题。链接:https://superuser.com/questions/561658/how-can-i-resume-a-large-scp-file-transfer-when-using-port-forwarding。 - Dan Dascalescu
rsync默认在底层使用ssh。通常情况下,rsync默认配置为使用ssh,因此它的速度应该与ssh相当(尽管它首先执行目录列表,这可能会导致启动较慢)。 - rogerdpack
7个回答

302
你应该使用ssh上的rsync
rsync -P -e ssh remoteuser@remotehost:/remote/path /local/path

关键选项是-P,它与--partial --progress相同。

默认情况下,如果传输被中断,rsync将删除任何部分传输的文件。在某些情况下,保留部分传输的文件更为理想。使用--partial选项告诉rsync保留部分文件,这应该使得随后传输文件的其余部分更快。

其他选项,例如-a(归档模式)和-z(启用压缩)也可以使用。

手册:https://download.samba.org/pub/rsync/rsync.html


88
想要说明的是,使用rsync可以很好地恢复从scp开始的批量复制。 - Craig Anderson
19
如果不指定-r选项,你将会遇到“跳过目录.”的错误。参考来源:http://lucasb.eyer.be/snips/rsync-skipping-directory.html - Artur Czajka
6
对我有用,但是我也加上了 --append.... rsync -P --append -e ssh remoteuser@remotehost:/remote/path /local/path - cnd
2
@CraigAnderson 这是被遗漏的重要点。回答听起来像是建议一开始就应该使用 rsync 开始下载。 - Willa
3
你可以在ssh命令中添加选项。我能够通过跳板继续进行scp复制,方法是:rsync -r -P -e 'ssh -J jumpuser@jumphost' /local/path remoteuser@remotehost:/remote/path - xvan
显示剩余8条评论

54

一种替代rsync的方法:

使用sftp命令,加上-r选项(递归复制整个目录)和sftpget命令的-a选项“继续传输部分已存在的文件”。

前提条件:您的sftp实现已经具备了带有-a选项的get命令。

示例:

将远程服务器上的目录/foo/bar复制到您本地的当前目录。目录bar将在您的本地当前目录中创建。

echo "get -a /foo/bar" | sftp -r user@remote_server

12
你的解决方案很好,因为我的服务器不允许通过ssh登录,所以rsync无法工作。我需要上传而不是下载,因此这是我的命令: echo "put -a foo/bar" | sftp -r server:/foo - Carlos Rafael Ramirez
3
这似乎是恢复部分下载文件的更可行选项,因为rsync对SSH不太友好(使用非默认端口)。 - Mehdi Haghgoo
3
这也适用于Windows,不需要rsync。 - Anton K
2
@codezombie 尝试使用rsync -P -e "ssh -p 2022" remoteuser@remotehost:/remote/path /local/path来访问通过端口2022的ssh等。您还可以像这样传递任何其他ssh选项。 - Pozzo-Balbi

28

10
另一个可能的方法是在scp停滞时尝试挽救已经开始的进程。
使用ctrl+z将其置于后台并停止,然后ssh到接收服务器并登录,然后退出。现在fg scp进程并观察它从“停滞”状态恢复!

1
在Mac OS X上对我有用。谢谢你发布这个,今天它救了我的命! - Ben Hitchcock
4
踢一下那个网络,看它能否自行恢复 :) - rogerdpack
可以使用另一个终端来进行第二个SSH连接,而不是使用“CTRL+Z”和“fg”。 - Kai Petzke
非常适用于卡住的正在进行中的scp。谢谢! - Adam Smooch

8

当rsync在最初运行良好的几秒钟后也停滞不前时,我采用以下蛮力解决方案,每60秒开始、停止和重新启动下载:

cat run_me.sh
#!/bin/bash
while [ 1 ]
do
  rsync --partial --progress --rsh=ssh user@host:/path/file.tgz file.tgz &
  TASK_PID=$!
  sleep 60
  kill $TASK_PID
  sleep 2
done

1
你可以利用rsync的-rsh和-P选项。-P是用于部分下载,而-rsh表示传输是通过ssh协议进行的。
完整的命令将是: rsync -P -rsh remoteuser@remotehost:/remote/path /local/path

与Jordi的答案相同? - rogerdpack
2
这是哪个版本的rsync?我的相对较新的版本(rsync版本3.1.2协议版本31)没有单破折号的“-rsh”选项,只有手册中说的“--rsh=COMMAND”,它是“-e COMMAND”的同义词。 - Michael Firth

-6

最佳实践是将URL中相关部分复制到答案中,以防网站崩溃。 - Ryre
我正在尝试上传,所以不能使用wget。 - Rolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接