为什么 dd 会暂停 5 秒,然后继续 20 秒,然后再次暂停?

为什么 dd 会暂停 5 秒,然后继续 20 秒,然后再次暂停?

我正在创建丢失数据的硬盘的副本,以便尝试从磁盘副本中恢复数据并保证原始数据安全。我在 Mac 上使用 dd,它在其他驱动器和存储介质上工作得很好,可以创建整个驱动器的精确副本。

我让 dd 运行了 45 个小时,在此期间它只复制了 410GB。我注意到磁盘指示灯停止周期性闪烁 5 秒,活动监视器显示只写入了 360GB,但读取了 410GB。我使用 pv 查看管道,这样我就可以知道它进展了多少,它也报告了 410GB,所以我认为活动监视器在测量写入数据量方面是不准确的。此外,在活动监视器中显示读写操作的图表中,它只显示了读取操作的变化,但写入图表只是平坦的,没有显示任何发生的情况。我认为负责写入输出文件的第二个 dd 进程可能已被锁定。

第一次尝试花了很长时间,但只写了几秒钟,然后立即暂停了很长时间,而且越接近操作结束时情况就越糟。当电脑重新启动时,我发现输出文件实际上是 410GB,就像活动监视器中的读取操作所建议的那样,所以写入操作的估计相当不正确。我注意到活动监视器总是给出错误的写入字节数,所以我不再相信活动监视器说的话,为什么它如此不一致?

我不想让需要恢复数据的旧硬盘磨损。它随时可能坏掉,尤其是如果我连续几天运行它并进行大量读取操作的话。

为什么 dd 会不断暂停,为什么随着时间的推移情况会变得越来越糟?它开始时非常快,但随着数据量的增加,它开始变得越来越慢,并且花费更多时间似乎什么都不做或等待某事。它在做什么?有没有更好的方法将磁盘复制到文件并使其成为驱动器上每个字节的精确副本?

以下是一些 IO 活动图表:

开始后立即:

开始

4小时后:

4小时后

11小时后:

11小时后

26小时后:

26小时后!


我使用提供的不同方法对旧的 USB 盘进行了一些复制测试。所有文件的校验和都相同,所有这些方法都在单个线程上运行。结果并不像我预期的那样:

  • 日:42:07
  • ddrescue:47:22
  • 猫:42:36
  • 時間: 42:38

答案1

你问, ”为什么 dd 会不断暂停并且为什么随着时间的推移情况会变得越来越糟?

没有数据就不可能给出明确的答案,但有可能,

  • 您的内存目标磁盘缓存已满,暂停是为了让缓存完成写入物理磁盘。对于 USB 连接设备尤其如此(但并非唯一如此)
  • 您的源磁盘存在硬件错误,导致无法轻松读取某些磁盘块。在这种情况下,您可以ddrescue尽可能地进行恢复(见下文)。

根据您随时间变化的 IO 图表,我认为您的磁盘有故障。

然后你问,“有没有更好的方法将磁盘复制到文件并使其成为驱动器上每个字节的精确副本?“。 就在这里。

如果你有这样的命令dd if=/dev/source_disk of=/dev/target_disk(用适当的值替换source_disktarget_disk),那么你使用的dd效率很低,而且运行速度会非常慢*。以下是两种解决方案

  1. 如果源磁盘良好,则使用catpv代替dd

    cat /dev/source_disk >/dev/target_disk
    pv /dev/source_disk >/dev/target_disk     # If you have pv installed
    
  2. 如果源磁盘可能有故障,则使用ddrescue而不是dd。您需要通过 Homebrew ( brew install ddrescue) 或其他第三方工具存储库安装它:

    ddrescue /dev/source_disk /dev/target_disk /some/temporary/logspace
    

    确保logspace文件不在 上,/dev/source_disk也不在 上/dev/target_disk

在两种情况下/dev/source_disk,都/dev/target_disk必须卸载并且不要使用。


* 有很多很好的答案这里尤其是Unix 和 Linux这解释了为什么dd在许多用例中它被错误且无效地使用。这里的问题是 (a) 它dd使用 512 字节的默认块大小,因此需要多次读取硬盘上的每个数据块(SSD 上每个块读取八次),以及 (b) 任何硬件读取错误都将被底层磁盘子系统多次重新读取,以及 (c) 这种永久读取错误无法进行有用的恢复cat不慢比默认设置dd要快得多,在简单直接的情况下使用时

答案2

热量?我见过电子元件的性能在温度升高或降低时会下降(而不是失效),特别是在温度升高之后。

答案3

运行时,dd您可以使用Ctrl- T(又名状态)来显示当前状态dd

load: 2.46  cmd: dd 33584 running 0.53u 0.79s
2619487+0 records in
2619487+0 records out
1341177344 bytes transferred in 1.325725 secs (1011655769 bytes/sec)

(啊哈,如果所有设备都能运行得这么快/dev/zero...... /dev/null

这将告诉您dd双方实际做了什么。

请注意,在某些情况下 ( conv=noerror)dd可以跳过输入中的错误,但默认情况下会跳过输出中的错误,这意味着错误后的数据将不会位于同一位置,并且可能毫无用处。为了避免这种情况,您还需要指定sync(即conv=noerror,sync)。但这还有很多注意事项,所以dd可能不是最好的工具。

相关内容