使用 DD 进行磁盘克隆

fal*_*tro 207 dd disk-image

有很多关于磁盘克隆工具的问题,并且dd至少被提出过一次。我已经考虑过使用dd自己,主要是因为它易于使用,而且几乎所有可启动的 Linux 发行版都可以使用它。

dd克隆磁盘的最佳方法是什么?我在 Google 上进行了快速搜索,第一个结果是一次明显失败的尝试。使用后有什么我需要做的吗dd,即有什么不能使用的dd

Ada*_*ins 190

dd 无疑是最好的克隆工具,它只需使用以下命令即可创建 100% 副本。我从来没有遇到过任何问题。

dd if=/dev/sda of=/dev/sdb bs=32M
Run Code Online (Sandbox Code Playgroud)

请注意,在克隆每个字节时,不应在正在使用的驱动器或分区上使用它。尤其是像数据库这样的应用程序无法很好地处理这种情况,您最终可能会得到损坏的数据。

  • 只是要非常小心'i'和'o'字母...... (143认同)
  • 添加“bs=100M conv=notrunc”,根据我的经验,它要快得多。 (27认同)
  • 似乎没有人知道这个技巧...... dd 是一个非对称复制程序,这意味着它会先读取,然后写入,然后返回。您可以通过管道将 dd 连接到自身并强制它对称地执行复制,如下所示:`dd if=/dev/sda | dd of=/dev/sdb`。在我的测试中,在没有管道的情况下运行命令给了我 ~112kb/s 的吞吐量。使用管道,我得到了大约 235kb/s。我从未遇到过这种方法的任何问题。祝你好运! (19认同)
  • @Mistiry,这不是对称这个词的意思。 (15认同)
  • 当然,只要/dev/sdb至少和/dev/sda一样大... (13认同)
  • 与 `cat /dev/sda > /dev/sdb` 或 `pv /dev/sda > /dev/sdb` 相比,使用 `dd` 有什么优势? (10认同)
  • notrunc 意味着(根据手册页):不截断输出文件。我不明白它怎么能更快。您可以使用以下命令跟踪操作的进展: # dd if=/dev/sda of=/dev/sdb & pid=$! # kill -USR1 $pid; 睡眠 1; 杀死 $pid (8认同)
  • 添加了 bs=32M,以节省未来读者克隆具有过时默认块大小的磁盘的痛苦。 (8认同)
  • @Eddie - 当然分区表也会被复制,所以如果 sdb 更大,你最后会有未使用的空间。 (7认同)
  • @bandi 时间似乎在您按下 Enter 键之前的一秒内缓慢地爬行。 (6认同)
  • 使用选项 `conv=sync,noerror` 非常重要,这样它就可以正确跳过坏块......除非你碰巧确定你的磁盘没有坏块,这在一般情况下是不正确的。 (6认同)
  • 添加“状态=进度”。此参数将显示“dd”在克隆过程中的位置。像这样:`dd if=/dev/sda of=/dev/sdb bs=32M status=progress` (5认同)
  • @Tim, conv=notrunc 究竟做了什么? (4认同)
  • 开始时稍微玩一下 bs。我遇到过任何 bs > 4k 由于某种原因而减慢进程速度的系统。如果两个驱动器都是内部驱动器(ide/sata),这可能不是问题,但如果涉及网络共享或 USB 磁盘,请注意块大小。 (3认同)
  • 哦是的。我已经使用了很多次 dd 并且它总是让我不寒而栗,当我想当我最终将那些“i”和“o”弄错时会有什么感觉.. (2认同)
  • @bandi 我已经编写了 dd 脚本,以便在执行它之前显示一个提示,说“你绝对确定 if 和 of?”。它需要输入“是”才能继续。当然,这是在我厌倦了 3Tb 的完美数据之后。 (2认同)
  • 如果您要恢复分区,请不要忘记运行“partprobe -s”,否则操作系统将不会收到有关分区表更改的通知。 (2认同)

Dav*_*cks 127

为了节省空间,您可以使用 gzip 压缩 dd 生成的数据,例如:

dd if=/dev/hdb | gzip -c  > /image.img.gz
Run Code Online (Sandbox Code Playgroud)

您可以使用以下方法恢复磁盘:

gunzip -c /image.img.gz | dd of=/dev/hdb
Run Code Online (Sandbox Code Playgroud)

为了节省更多空间,请事先对要克隆的驱动器/分区进行碎片整理(如果合适),然后将所有剩余的未使用空间清零,以便 gzip 更容易压缩:

mkdir /mnt/hdb
mount /dev/hdb /mnt/hdb
dd if=/dev/zero of=/mnt/hdb/zero
Run Code Online (Sandbox Code Playgroud)

稍等一下,dd 最终会失败并显示“磁盘已满”消息,然后:

rm /mnt/hdb/zero
umount /mnt/hdb
dd if=/dev/hdb | gzip -c  > /image.img.gz
Run Code Online (Sandbox Code Playgroud)

此外,您可以通过使用 kill 命令向其发送信号来让 dd 进程在后台运行以报告状态,例如:

dd if=/dev/hdb of=/image.img &
kill -SIGUSR1 1234
Run Code Online (Sandbox Code Playgroud)

检查您的系统 - 上述命令适用于 Linux,OSX 和 BSD dd 命令在它们接受的信号方面有所不同(OSX 使用SIGINFO- 您可以按Ctrl+T报告状态)。

  • +1 为`kill -SIGUSR1 %1`,OSX dd 命令愉快地接受 SIGUSR1 ......非常有用,谢谢! (4认同)
  • 应该是:`dd if=/dev/hdb | gzip -c > /image.img.gz` ? (3认同)
  • 这是否也适用于“现代”fs,例如 BTRFS、NILFS,[无论您梦想什么]? (2认同)

jld*_*ger 44

注意:添加实时文件系统可能会损坏文件。原因很简单,它不了解可能发生的文件系统活动,也没有尝试缓解它。如果写入部分正在进行,您将获得部分写入。这通常对事物不利,对数据库通常是致命的。此外,如果你搞砸了容易打错字的ifof参数,那你就惨了。在大多数情况下,rsync是在multitasking出现之后编写的同样有效的工具,它将提供单个文件的一致视图。

但是,DD 应该准确地捕获未安装驱动器的位状态。引导加载程序、llvm 卷、分区 UUID 和标签等。只需确保您有一个能够逐位镜像目标驱动器的驱动器。

  • 我怀疑`sync` 不是解决文件损坏问题的方法。在 `dd` 操作期间,如果守护程序或其他东西在 `sync` 之后写入更多文件,会发生什么? (8认同)
  • 最好先卸载驱动器(或重新挂载为只读),但并非总是可行 (6认同)
  • 我想补充一点,在挂载的文件系统上运行 dd 不会损坏挂载的文件系统上的文件,但这里的意思是文件系统的副本必须处于已知的良好状态。 (4认同)

Tim*_*imB 29

当使用dd克隆可能包含坏扇区的磁盘,使用conv=noerror,sync,以确保当它遇到一个错误就不会停止,而在缺少行业与空字节填充(S)。如果尝试从故障或故障磁盘中恢复,这通常是我采取的第一步 - 在进行任何恢复尝试之前获取副本,然后在好的(克隆)磁盘上进行恢复。我把它留给恢复工具来处理任何无法复制的空白扇区。

此外,您可能会发现ddbs(块大小)设置会影响 的速度。我通常会尝试bs=32768,但您可能想在自己的系统上测试它,看看哪种方法最适合您。(这假设您不需要出于其他原因使用特定的块大小,例如,如果您正在写入磁带。)

  • 如果您的磁盘有坏扇区,您真的应该使用“ddrescue”而不是 dd。它效率更高,并且更有可能恢复更多数据。(不要把它与 dd_rescue 混淆,它不是那么好) (15认同)
  • 如果试图跳过坏块,则不应使用大块大小,否则会跳过太多。4096够大了。 (5认同)

Kyl*_*nin 17

要克隆磁盘,您真正需要做的就是指定 dd 的输入和输出:

dd if=/dev/hdb of=/image.img
Run Code Online (Sandbox Code Playgroud)

当然,请确保您具有直接从 /dev/hdb 读取的适当权限(我建议以 root 身份运行),并且 /dev/hdb未安装(您不想在磁盘处于正在更改 - 以只读方式安装也是可以接受的)。完成后,image.img 将是整个磁盘的逐字节克隆。

使用 dd 克隆磁盘有一些缺点。首先,dd 将复制您的整个磁盘,甚至是空白空间,如果在大磁盘上完成,可能会导致非常大的图像文件。其次,dd 绝对不提供进度指示,这可能令人沮丧,因为复制需要很长时间。第三,如果您将此映像复制到其他驱动器(再次使用 dd),它们必须与原始磁盘一样大或大于原始磁盘,但是您将无法使用目标磁盘上可能具有的任何额外空间,直到您调整分区大小。

您还可以直接进行磁盘到磁盘复制:

dd if=/dev/hdb of=/dev/hdc
Run Code Online (Sandbox Code Playgroud)

但您仍然受到上述有关可用空间的限制。

就问题或陷阱而言,dd 在大多数情况下做得非常出色。然而,不久前我有一个硬盘快要死了,所以我用 dd 尝试在它完全死之前复制我可以删除的信息。后来得知 dd 不能很好地处理读取错误 - 磁盘上有几个 dd 无法读取的扇区,导致 dd 放弃并停止复制。当时,尽管遇到读取错误,但我找不到告诉 dd 继续的方法(尽管看起来它确实具有该设置),因此我花了很多时间手动指定跳过并寻求跳过不可读的部分。

我花了一些时间研究这个问题的解决方案(在我完成任务后),我发现了一个名为ddrescue的程序,根据该站点的说法,它的运行方式与 dd 类似,但即使遇到错误也会继续阅读。我从未真正使用过该程序,但值得考虑,特别是如果您从中复制的磁盘很旧,即使系统看起来很好,它也可能有坏扇区。

  • **...dd 绝对没有提供进度指示...** - 这不是真的 - 如何显示进度有点棘手 - 你必须找出 dd 进程的 pid ('ps -a | grep dd ') 然后将信号 USR1 发送到这个进程 - 'kill -USR1 <dd_pid_here>'(没有 <>) 强制 dd 显示进度信息。 (7认同)
  • “dd 无法读取磁盘上的几个扇区”:我认为 `conv=sync,noerror` 会有所帮助。 (4认同)
  • 使用 dd 取得进展的一种不太棘手的方法是添加选项 `status=progress` (3认同)
  • `conv=sync,noerror` 选项是必不可少的,它们允许 dd 跳过坏块并将它们在图像中归零,以便正确对齐。向极少数对此发表评论的人表示支持。 (2认同)
  • GNU `ddrescue` 提供了进度指示器,没有任何特殊选项,您可以停止复制并从中断处继续。 (2认同)

Ben*_*ams 13

如果源驱动器完全损坏,则使用dd_rhelpwith dd_rescue(我个人偏好)或 GNU会更幸运ddrescue

这背后的原因是,在读取错误时,dd不断尝试、尝试和尝试 - 可能等待很长时间才能发生超时。dd_rescue做一些聪明的事情,例如读取错误,然后在磁盘上进一步选择一个点并反向读取到最后一个错误,并且dd_rhelp基本上是一个dd_rescue会话管理器 - 巧妙地启动和恢复dd_rescue运行以使其再次更快。

最终结果dd_rhelp是在最短的时间内恢复了最多的数据。如果您dd_rhelp停止运行,最终它会完成dd与同一时间完全相同的工作。但是,如果dd在 100Gb 磁盘的第 100 字节处遇到读取错误,则必须等待很长时间才能恢复其他 9,999,900 字节*,而dd_rhelp+dd_rescue会更快地恢复大部分数据。


ret*_*ile 8

源磁盘不能有任何挂载的文件系统。作为能够读取块设备(root 工作)的用户,运行“dd if=/dev/sda ....”

现在,这里的一件巧妙的事情是你正在创建一个字节流......你可以用它做很多事情:压缩它,通过网络发送它,把它分成更小的 blob,等等。

例如:

dd if=/dev/sda | ssh user@backupserver "cat > backup.img"
Run Code Online (Sandbox Code Playgroud)

但更强大的是:

dd if=/dev/sda | pv -c | gzip | ssh user@backupserver "split -b 2048m -d - backup-`hostname -s`.img.gz"
Run Code Online (Sandbox Code Playgroud)

以上将源硬盘的压缩映像复制到远程系统,在那里它使用源主机的名称将其存储在编号为 2G 的块中,同时让您了解进度。

请注意,取决于磁盘大小、源上的 cpu 速度、目标上的 cpu 速度、网络速度等。您可能希望跳过压缩,或者在远程端进行压缩,或者启用 ssh 的压缩。


Jam*_*ers 6

要克隆磁盘,您真正需要做的就是将输入和输出指定为dd

dd if=/dev/hdb of=hdb.img
Run Code Online (Sandbox Code Playgroud)

当然,请确保您具有直接读取的适当权限/dev/hdb(我建议以 root 身份运行),并且/dev/hdb没有挂载(您不想在更改磁盘时进行复制)。一旦完成,hdb.img就会对整个磁盘进行逐字节克隆。

dd用于克隆磁盘有一些缺点。首先,dd将复制你的整个磁盘,甚至是空白空间,如果在大磁盘上完成可能会导致图像文件非常大。其次,dd绝对不提供进度指示,这可能令人沮丧,因为复制需要很长时间。第三,如果您将此映像复制到其他驱动器(再次使用 dd),它们必须与原始磁盘一样大或大于原始磁盘,但是您将无法使用目标磁盘上可能具有的任何额外空间,直到您调整分区大小。

您还可以直接进行磁盘到磁盘复制:

dd if=/dev/hdb of=/dev/hdc
Run Code Online (Sandbox Code Playgroud)

但您仍然受到上述有关可用空间的限制。

第一个缺点可以通过在复制时对数据进行 gzip 来解决。例如:

dd if=/dev/hdb | gzip -9 > hdb.img.gz
Run Code Online (Sandbox Code Playgroud)

第二个缺点可以通过使用 pipeview ( pv) 工具来解决。例如:

dd if=/dev/hdb | (pv -s `fdisk -l /dev/hdb | grep -o '[0-9]*\{1\} MB' | awk '{print $1}'`m) | cat > hdb.img
Run Code Online (Sandbox Code Playgroud)

我知道没有办法克服第三个缺点。

此外,您可以通过告诉dd使用更大的数据块来加快复制时间。例如:

dd if=/dev/hdb of=hdb.img bs=1024
Run Code Online (Sandbox Code Playgroud)

  • @Tozz:您可以通过用填充为 0 的文件填充文件系统,将其同步到磁盘,然后将其删除来提高文件系统映像的可压缩性。`dd if=/dev/zero bs=1M of=/balloon; 同步; rm /balloon`(文件系统层中的模数额外智能。) (3认同)

小智 5

您可以使用 dd 和救援磁盘做的另一件好事是通过网络复制数据:

remote_machine$ nc -l -p 12345

local_machine$ dd if=/dev/sda | nc remote_machine 12345
Run Code Online (Sandbox Code Playgroud)

如果网络不是本地的,您可以在这两个管道中粘贴 gzip。要取得进展,请使用pv. 为了让local_machine的netcat在复制完成后退出,你可以添加-w 5什么。

  • 这并不完全正确。'remote_machine' 命令缺少某些内容,例如 `> disk_backup.img` 或 `|dd of=/dev/sdb` 或其他内容,具体取决于您要执行的操作。我猜您不想将磁盘映像转储到标准输出。 (9认同)

Sam*_*ins 5

dd if=/dev/sda of=/dev/sdb bs=4096 conv=sync,noerror
Run Code Online (Sandbox Code Playgroud)

这将复制磁盘,并跳过有错误的块,这非常重要。

这些是使用 dd 克隆或拯救磁盘的基本和必要选项。

我不想发布另一个答案,但是在已经发布的 25 个答案中,基本的“conv=sync,noerror”选项没有很好的答案。