osh*_*nen 44 dd cloning hard-disk
原问题:
完整的 dd 副本需要多长时间才能完成?
到目前为止,它已经运行了 5 个小时,但仍在继续……
我使用的是 Linux Ubuntu 12.04 64bit,我使用的命令是:
dd if=/dev/sdb of=/dev/sdc
Run Code Online (Sandbox Code Playgroud)
更新:1
我现在可以看到进度了,复制 430GB 已经超过 6 个小时了。硬盘是3TB...
没有更快的方法吗?
更新:2
sudo dd if=/dev/sdb bs=128K | pv -s 3000G | sudo dd of=/dev/sdc bs=128K
Run Code Online (Sandbox Code Playgroud)
3TB 的 ETA 大约需要 9 小时,而在 6 小时后达到 430GB 之前,我猜使用前面的命令大约需要 36 小时。
Gil*_*il' 70
dd
在过去人们使用磁带(当块大小很重要时)以及更简单的工具(例如cat
可能不是二进制安全的)时很有用。
如今,dd if=/dev/sdb of=/dev/sdc
只是一种复杂、容易出错、缓慢的写作方式cat /dev/sdb >/dev/sdc
。虽然dd
对于一些相对罕见的任务仍然有用,但它的用处远不如提到它的教程数量会让您相信。没有魔法在dd
,魔法全在/dev/sdb
。
你的新命令sudo dd if=/dev/sdb bs=128K | pv -s 3000G | sudo dd of=/dev/sdc bs=128K
再次不必要地缓慢和复杂。一次读取 128kB 的数据(这比dd
默认的 512B 好,但不如更大的值)。然后在写入之前通过两个管道。
使用更简单、更快的cat
命令。(在我几年前在 Linux 下进行的一些基准测试中,cat
比cp
在不同磁盘之间复制cp
要快,并且比dd
任何块大小dd
都快;当复制到同一个磁盘时,大块大小稍微快一些。)
cat /dev/sdb >/dev/sdc
Run Code Online (Sandbox Code Playgroud)
如果要在 中运行此命令sudo
,则需要以 root 身份进行重定向:
sudo sh -c 'cat /dev/sdb >/dev/sdc'
Run Code Online (Sandbox Code Playgroud)
如果您想要一份进度报告,因为您使用的是 Linux,您可以通过记录cat
进程的 PID (比如 1234)并查看其输入(或输出)文件描述符的位置来轻松获得。
# cat /proc/1234/fdinfo/0
pos: 64155648
flags: 0100000
Run Code Online (Sandbox Code Playgroud)
如果你想有一个进度报告和您的UNIX系统没有提供一种简单的方法来获得在文件描述符的位置,就可以安装和使用pv
代替cat
。
fro*_*utz 10
dd
默认情况下使用非常小的块大小(512 字节)。这会导致大量开销(每 512 个字节一个read()
和write()
系统调用)。
当您使用更大的块大小时,它会快得多。最佳速度开始于bs=64k
左右。大多数人使用更大的,bs=1M
所以它变得人类可读(当dd
说它被复制时1234 blocks
,你知道它1234 MiB
没有做任何数学运算)。使用更大的块大小不太可能导致速度提高,只会增加内存消耗。
所以命令应该是:
dd bs=1M if=/dev/sdb of=/dev/sdc
Run Code Online (Sandbox Code Playgroud)
如果您的dd
运行速度已经很慢,您可以中断它并使用更快的dd
实例继续运行。为此,重要的是要知道复制已经进行了多远。dd
通常在您取消它时打印进度,或者您可以USR1
在它运行时向它发送信号以使其打印其进度。
kill -USR1 $(pidof dd)
Run Code Online (Sandbox Code Playgroud)
例如,如果它复制了多个1234MiB
,您可以1234MiB
使用以下命令在位置恢复:
dd bs=1M seek=1234 skip=1234 if=/dev/sdb of=/dev/sdc
Run Code Online (Sandbox Code Playgroud)
如果复制的数量少于1234MiB
,您的副本将不完整。如果它复制了超过1234MiB
,它会重新复制一些已经复制的部分,这通常不会造成任何伤害。因此,如果有疑问,您应该选择一个比您认为已经复制的值略小的值。
您可以使用kill
带有适当信号的命令将dd
输出统计为标准错误。
从 GNU dd 手册页:
Sending a USR1 signal to a running 'dd' process makes it print I/O statistics to standard error and then resume copying.
$ dd if=/dev/zero of=/dev/null& pid=$!
$ kill -USR1 $pid
18335302+0 records in 18335302+0 records out 9387674624 bytes (9.4 GB) copied, 34.6279 seconds, 271 MB/s
Run Code Online (Sandbox Code Playgroud)
确保首先检查您的手册页以获取正确的信号,因为它在不同的 dd 实现上可能有所不同:(BSD dd 使用 SIGINFO)。
bs=
参数使用适当的块大小。看看这个关于超级用户的线程并为自己尝试一些值。dd
调用进行读取和写入,并使用管道将它们连接起来 ( dd if=/dev/sda bs=1M | dd of=/dev/sdb bs=1M
)。direct
参数。