与 ddrescue 一起使用多个不同的 `--input-position` 是否安全?

与 ddrescue 一起使用多个不同的 `--input-position` 是否安全?

我需要从某个 2 TB 的大硬盘中恢复数据,并在某个 VM 中的某个 Live-Linux 中进行此操作,有问题的硬盘使用 USB 3 连接到该 VM,VM 在本地提供所需大小的虚拟磁盘来接收数据。然后我执行了以下调用,只是为了看看事情进展如何:

ddrescue -f /dev/sdc /dev/sdb /mnt/sda1/ddrescue.map

sdc是USB处损坏的设备,sdb是接收数据的虚拟磁盘,sda1用于临时存储并使用Ext4格式化。

一切开始快速运转,ddrescue几分钟内就能读取约 45 GB 的数据,然后速度大幅下降,几天内只能以每秒几字节的速度读取。所以设备显然是在这些部分出了问题,我试图简单地跳过这些部分,使用多个不同的调用--input-position=[...]GB一个接一个。根据我跳转到的位置,事情开始再次快速读取,直到它们再次变慢,我再次使用另一个调用跳转。需要注意的重要一点是,打印的输入和输出位置ddrescue始终是同步的!我也没有手动更改提供的映射文件中的任何内容,也没有删除它或其他什么,它一直都是同一个文件,只由ddrescue它自己管理。

后来我稍微改变了方法并决定不再--input-position手动使用,而是改为使用以下内容:

ddrescue -f --min-read-rate=1MB --skip-size=1MB /dev/sdc /dev/sdb /mnt/sda1/ddrescue.map

因此,每当ddrescue识别出速度较慢的部分时,它就会跳过合理的损坏数据块并继续读取。同样,输入和输出位置同步,读取和恢复数据的计数器一直在增加。到目前为止,已经ddrescue完成,据说已经恢复了约 650 GB 的数据。

问题是,在最终查看虚拟磁盘文件本身后,似乎实际存储的数据只有约 160 GB。此外,上次写入时间戳也早了几天。因此,出于某种原因,它ddrescue认为它正在读取大量数据,但似乎没有在虚拟磁盘中从损坏的磁盘读取数据的位置正确写入数据。最后,据我所知,虚拟磁盘至少应该具有ddrescue与它所拯救的数据量相当的大小。

我感觉它ddrescue正确地读取了它所说的所有数据,但在后续调用中只是覆盖了已经恢复的数据。因此,虽然我猜它识别了--input-position要读取的数据,但它似乎总是从目标位置 0 开始写入。

显然我没有指定写入数据的起始位置,但是根据文档这不是必需的,并且ddrescue打印的输入和输出位置无论如何总是相同的。

-o bytes
--output-position=bytes
Starting position of the image of the rescue domain in outfile, in bytes.
Defaults to '--input-position'. The bytes below bytes aren't touched if 
they exist and truncation is not requested. Else they are set to 0.

当然,我没有请求截断,根据文档,它默认未启用,甚至对于我指定的目标驱动器也不起作用:

-t
--truncate
Truncate outfile to zero size before writing to it. Only works for regular
files, not for drives or partitions.

那么,你知道可能出了什么问题吗?我多次调用不同的值是否已经出错--input-position了?这是否与读取和写入驱动器(而不是分区或文件)有关?

可能是写入虚拟磁盘时出现问题?虽然我不明白这有什么区别,我需要写入虚拟磁盘,但无法提供所需大小的原始设备存储。

谢谢!

答案1

使用多个不同的 ddrescue 是否安全--input-position

好像我以前错过了这个例子,但这实际上是我所做的,它表明我的方法得到了支持:

Example 5: While rescuing a partition in /dev/sda1 to the file hdimage, /dev/sda1 stops responding and begins returning read errors, causing ddrescue to mark the rest of the partition as non-scraped.
     ddrescue -n /dev/sda1 hdimage mapfile        <-- /dev/sda1 fails here
       (restart /dev/sda or reboot computer)
     ddrescue -n -A -i<pos> -O /dev/sda1 hdimage mapfile
       (if /dev/sda1 fails again, restart /dev/sda or reboot computer and
        then repeat the above command as many times as needed until it
        succeeds. <pos> is the position where the drive stopped responding)
     ddrescue -d -r3 /dev/sda1 hdimage mapfile

https://www.gnu.org/software/ddrescue/manual/ddrescue_manual.html#Examples

第二次调用显然被记录为在不同位置重复。至于如何ddrescue使用其映射文件,这也是有道理的,因为它总是知道使用该文件哪些块已经被读取。

因此,我遇到的问题很可能与此不同,尤其是我认为我识别出的太旧的时间戳很奇怪。也许我只是因为某种原因错过了未写入实际目标设备的消息。虚拟机本身也在另一个 USB 驱动器上,也许存在一些连接错误导致 Live-Linux 在运行时错过该设备或类似情况。由于记录了所有读取错误,ddrescue我很容易错过此类错误。dmesg -T

听起来我需要重复整个过程......

答案2

我阅读了ddrescue手册,没有任何地方提到多个input-position参数的可能性。

此参数总是以“a”或“the”的形式提及,因此它似乎必须是唯一的。

问题的根源可能是手册中的这句话:

请注意,您必须保留原始救援运行的“--input-position”和“--output-position”之间的原始偏移量。

这似乎与以下另一段内容一致:

Ddrescue 在输入中发现坏扇区时不会将零写入输出,并且不会在未要求时截断输出文件。因此,每次在同一个输出文件上运行它时,它都会尝试填补空白,而不会清除已挽救的数据。

这意味着它ddrescue会记住第一次运行的参数,因此您应该始终保留相同的参数,或者可能只是在后续运行中不指定它们(我不能说哪个是正确的)。完全有可能记住一些参数,而您的新参数在后续运行中被忽略。

如果磁盘的元表的某些部分已损坏,您看到的数据可能会比实际挽救的少,因为似乎没有文件包含这些部分。

无法挽救的数据ddrescue需要使用其他恢复产品进行恢复。这可能需要很长时间,甚至可能无法使用您可用的产品。如果必须恢复数据,专业的恢复公司可能能够从原始磁盘进行恢复,但这些服务价格昂贵。

答案3

由于的手册页很长,因此根据目标和用户级别的不同,ddrescue使用的方法也有很大差异。基本上,如果您使用 Live Linux,最好在物理机器而不是虚拟机上运行它,并且将磁盘连接到 SATA,而无需任何 SATA/USB 适配器。 其他功能可以绕过内核磁盘驱动程序和缓冲区,因此可以减少对坏簇的无用重复读取。mapfile(以前称为 logfile)保存有关所有未读取/成功读取簇的信息,这就是为什么您可以简单地重复崩溃步骤的原因。它在开始工作之前查找 mapfile,创建它,如果它不存在,则读取它,如果它可用,并从最后记录的位置开始继续救援工作。每次程序崩溃时,您无需手动移动起始位置!ddrescue
ddrescueddrescue

您可以使用各种选项使救援过程更快、更安全。您还可以(并且建议)将救援过程分为两个或更多步骤:

第一步:快速读取好的集群并立即跳过坏的集群。

第二步:处理上一步中未读的簇,并使用特殊选项来欺骗磁盘功能(NCQ、预读...),以便一次读取一个扇区。适当的命令(我使用):

ddrescue -n -p -d -r1    /dev/sdd $IMGPATH/disk.img $IMGPATH/disk.log;
ddrescue       -d -r3 -R /dev/sdd $IMGPATH/disk.img $IMGPATH/disk.log;
#         |  |  |  |   |
#         |  |  |  |   revers reading
#         |  |  |  retry read 1x (3x)
#         |  |  direct access to disk (bypass the kernel)
#         |  preallocate diskspace      
#         nonscrap

如果你的磁盘太热或者不喜欢太多的读取操作/秒,你可以使用以下选项减慢读取速度:--max-read-rate=50M

所以这只是第一次接触,但您可以在专业俱乐部或论坛上找到许多相关的建议ddrescue

相关内容