‘dd’ 命令执行时间太长了吗?

我设置了dd来克隆一个较小的系统40.00GB硬盘(/dev/sda)到一个通过USB读卡器连接的新的更大的111.00GB硬盘(/dev/sdb),现在已经进行了两个小时。新硬盘上的活动指示器显示它正在进行某些操作。但是CPU使用率只有大约20%。这个过程什么时候会完成?我应该重新启动这个过程吗?

1dd 命令是静默执行的,所以第一次使用时似乎需要很长时间。但请耐心等待。Unix 的理念是,除非出现错误提示,否则命令通常都在正常工作。有关详细信息,请参阅此答案:https://askubuntu.com/questions/435694/can-i-dd-a-larger-drive-to-a-smaller-one/936556#936556 - SDsolar
5个回答

在未来,您应该使用pv来获取一个正在运行的进度条。 sudo apt-get install pv 安装了pv之后,让我们假设您想要克隆一个20GB的驱动器/dev/foo到另一个大于或等于20GB的驱动器/dev/bazsudo dd if=/dev/foo bs=4M | pv -s 20G | sudo dd of=/dev/baz bs=4M 需要注意的重要部分:参数bs=4M将dd操作的块大小设置为4MB,这极大地提高了整个过程的速度。参数-s 20G告诉pv这个操作的预计大小,因此它可以给出估计的剩余时间以及当前的速度。
我非常喜欢pv,以至于可能应该是非法的。
请注意,虽然按照从左到右的顺序进行输入输出是直观、整洁的方式,但如果你处理的是非常快速的数据流,通过标准输出和管道传输可能会导致性能损失。以下语法更快,如果你要移动几百兆字节/秒的数据: pv -s 20G < /dev/foo > /dev/baz -s 20G 是可选的,如果你实际上知道流的大小(或者大致大小),它可以让 pv 给出完成时间的估计。如果没有这个参数,pv 将尝试根据可能的情况来确定数据集的大小(例如,它知道文件的大小),但如果无法确定(例如块设备而不是文件),它只会告诉你传输速率,而不会猜测需要多长时间。

1当然,PV非常有用,但如果你正在复制大量数据,它会增加更多的上下文切换和缓冲区拷贝,因此会消耗更多的CPU资源,可能会稍微减慢速度。但由于驱动器上的数据复制受到速率限制,所以不会增加太多额外开销。 - Colin Ian King
在实际操作中,你几乎不可能看到pv增加时间的0.1%。如果确实出现这种情况,那几乎肯定是一个如此快速的操作,以至于一开始就没有必要尝试添加进度条。 - Jim Salter
1太对了。我只是一个老派的工程师,习惯于尽可能地节约每个周期。 - Colin Ian King
@ColinIanKing - 今天我刚刚发现,虽然pv本身不会减慢速度,但是将数据通过标准输出和标准输入进行传输会有影响。对于从一个传统硬盘到另一个传统硬盘的普通dd操作,不会有任何影响...但是如果你使用的是非常高性能的SSD,就会有影响。我的新Intel 520 480GB SSD可以连续读取340MB/秒左右,但是如果像这样使用管道dd if=/dev/sda bs=4M | dd of=/dev/null bs=4M,速度只有276MB/秒左右。真是令人沮丧。(对于缓存读取来说,效果更糟糕,如果不经过管道,速度可能达到16GB/秒)。 - Jim Salter
14重新访问这个问题之后,经过与pv的作者一些交流,我发现你可以完全避免速度惩罚,只需将dd从方程中去掉:pv < /dev/sda > /dev/sdb 运行得很好,并且以底层硬件能够达到的速度运行。 - Jim Salter
谢谢 @JimSalter,我刚注意到我的管道命令:dd if=/dev/sda | pv | dd of=/file 分别占用了20%、60%和20%的CPU。对我来说,这似乎是个问题。 - isaaclw
1dd: bs: 非法的数值,所以我选择了 bs=32m。 - Jacksonkr
@JimSalter你应该把你的评论添加到你的回答中,因为评论经常被删除,谢谢。 - Shayan
Mac用户:可以使用Homebrew安装pv,命令为brew install pv。如前面的评论中提到的,M是非法的数值表示,所以请使用m代替,例如4m - Martin

你可以通过发送SIGUSR1信号来查看它的进展,以了解它已经复制了多少数据和传输速率。
kill -SIGUSR1 $(pidof dd)

对于复制活动,您受到设备的I/O速度限制,因此CPU不应该被完全占用,所以不用担心这个问题。

1明白了。嗯,我终止了这个进程,发现它进行得非常缓慢...不得不重新做分区表,但现在已经全部清空了。你知道有没有更好的方法来克隆硬盘而不会花费一整天的时间? - user101351
@SeanWebber:运行该命令实际上不会终止dd进程。根据man dd的说明:“向正在运行的dd进程发送USR1信号会使其将I/O统计信息打印到标准错误输出,然后继续复制。”为了加快进程速度,可以尝试像Jim Salter在另一个答案中建议的那样指定更大的块大小。 - Sergey
5OS X的dd命令肯定有问题,因为发送SIGUSR1信号也让它崩溃了。 - Jarrod Davis
5从其他地方:在BSD系统(如OSX)上杀死-INFO $(pgrep ^ dd $)。 - ThatOneDude
现在有一种更简单的方法可以从dd获取进度输出。看看我的答案! - Elder Geek
这会终止进程吗? - tjespe
不,SIGUSR1由dd处理,它不会杀死它。只有SIGKILL、SIGHUP等才会杀死它。 - Colin Ian King
我刚刚做了这个,它并没有终止进程。以下是示例输出: 10712217+0 条记录(换行) 10712217+0 条记录已复制(换行) 5484655104 字节(5.5 GB, 5.1 GiB)已复制,用时2233.64秒,速度为2.5 MB/s。 - pauljohn32
我喜欢这个,因为它不需要你从头开始复制才能看到进展。 - dawid

我过去曾使用pv以及(ps和kill),正如其他答案中建议的那样,但最近我只是使用dc3dd,它在整个过程中提供了进度报告,并产生了相同的结果。
您可以通过以下命令检查是否已安装:which dc3dd
如果没有安装,您可以使用sudo apt-get install dc3dd进行安装。
命令开关与dd类似(用于克隆,尽管擦除更加直接)。
在您的情况下,我会使用命令dc3dd if=/dev/sda of=/dev/sdb。
编辑:
Ubuntu 16.04及更高版本中包含的coreutils package版本8.24+的最新版本的dd命令包括一个status参数。您可以通过将status=progress开关添加到您的dd命令行中来实现相同的结果。

示例:dd if=/dev/zero of=/dev/null count=1000 status=progress


你可以使用ddrescue:
sudo ddrescue -v /dev/sda /dev/sdb

v代表着冗长的。

我遇到了类似的问题,但原因在我的情况下是不同的。
目标驱动器是一个外部硬盘。
如果通过udisksudisks-glue自动挂载磁盘,从光驱到硬盘的传输速率大约为40kB/s。
当我卸载硬盘并直接通过mount挂载时,传输速率约为2.4MB/s。

4请在此答案中添加更多信息,例如如何使用“mount”而不是“udisks”进行挂载。 - Parto