我需要将一个磁盘复制到另一个磁盘。我尝试使用下面的命令,在 federo 中复制 1 TB 磁盘需要将近一天的时间。
dd if=/dev/sda of=/dev/sdb
我在 Unix(HP-UX) 系统上使用下面的命令尝试了相同的操作,它在几个小时内完成
dd if=/dev/sda of=/dev/rdsk
我可以使用什么替代方法来更快地从磁盘复制到磁盘?
答案1
dd
有很多(奇怪的)选项,请参阅日(1)。
您应该明确说明缓冲区大小,因此请尝试
dd if=/dev/sda of=/dev/sdb bs=16M
IIRC,默认缓冲区大小仅为 512 字节。上面的命令将其设置为 16 MB。您可以尝试更小的东西(例如bs=1M
),但您应该使用比默认值更多的东西(特别是在具有 4Kbytes 扇区的最新磁盘硬件上,即高级格式)。我天真地推荐一些至少是一兆字节的二的幂。
使用默认的 512 字节缓冲区大小,我猜想(但我可能是非常错误的)硬件要求内核为每个 512 字节块传输 4K。
关于rdsk
,标准差(4)手册页说:
此时仅提供块设备。原始设备尚未实现。
增加 dd 的缓冲区大小将为您提供更好的读写操作性能。现在所有磁盘都有硬件读/写缓冲区。但是,如果将 dd 的缓冲区大小增加到超过硬件缓冲区,则其性能将会下降,因为当第二个磁盘从其自己的硬件缓冲区写入所有内容时,dd 将从第一个磁盘读取到缓冲区。您需要bs
每次为不同的设备设置不同的 dd 命令选项。
答案2
多年前,在 Unix 领域,dd
复制块设备是必需的方法。尽管(至少在基于 Linux 的系统上)cat
几乎总是比dd
.
然而,即使在历史上,考虑到每个系统调用都会触发一个 I/O 操作,适当的块大小也有助于减少(缓慢)系统调用的数量。默认块大小为 512 字节(一个磁盘扇区)。将多个磁盘块收集在一起进行一次读取过去也是可以接受的。此示例使用 32MB 块大小:
dd bs=$((512*2048*32)) if=/dev/source of=/dev/target
顺便说一句,如果您正在读取未压缩的流或来自远程网络源的流,您可能会发现短读取小于所需的块大小。这些应该通过告诉dd
重新读取直到获得足够的输入来填充块来处理,iflag=fullblock
;如果没有这个,您有时可能会得到损坏的输出流。这里的情况并非如此,但为了完整性我将其包括在内。
回到最初的问题,在当前基于 Linux 的系统上,可以通过简单的方法最有效地复制磁盘cat
cat /dev/source >/dev/target
(正如您的问题的评论中所指出的,pv
可以替换它cat
,并为您提供进度和吞吐量的指示。)
答案3
一般来说,dd
可以避免使用某些替代方案。使用 GNU 来代替有几个很好的理由ddrescue
。在 Ubuntu 中,您可以使用以下命令安装它:
sudo apt-get install gddrescue
简单地说ddrescue
易用。请注意,与包名称不同,可执行文件才不是有初始g
.
使用它非常简单:
ddrescue inputFile outputFile logFile
日志文件(无论您选择什么名称)都可以让您暂停/停止和重新启动,而无需重做之前的工作,这在进行大型克隆或磁盘恢复时非常有用。默认情况下,它显示进度、当前复制速度、平均复制速度和发现的坏块数量。
它对块大小使用合理的默认值,因此复制速度始终与设备可以处理的速度一样快,至少根据我的经验(我已经用它克隆了数百个驱动器,所有大小和类型)。
通常,开始出现故障的驱动器会出现速度问题,例如偶尔出现速度缓慢、平均速度较低、突然长时间暂停(坏扇区)或完全重置(严重的表面错误)。ddrescue
即使您的驱动器正在自行重置,也可以帮助您识别上述所有内容并重新启动克隆(前提是您指定了日志文件)。
答案4
非常好的问题。原始接口在某些 UNIX 系统(tru64、hpux、solaris)上实现,但在 Linux 上未实现。原始接口使传输速度更快,因为跳过了 UNIX I/O。块接口(/dev/dsk
或/dev/disk
)速度较慢,因为它使用 unix I/O 系统。要加速dd
(gnu dd 可以)使用bs=30M
或 ,bs=20M
具体取决于您的硬件。简短的回答是:不,至少据我所知,它还没有实施。我从内核版本 2.2 的旧时代开始就使用 Linux,从未见过rdsk
在 UNIX 上使用过。