我在恢复 ddrescue 时使用了错误的输出文件名,犯了一个愚蠢的错误。这就是发生的事情:
ddrescue -b 2048 -d -v /dev/sr1 IDTa.img IDTa.ddrescue.log
然后计算机崩溃了,我错误地恢复了:
ddrescue -b 2048 -d -v /dev/sr1 IDTa.iso IDTa.ddrescue.log
我收集到两个图像文件都会开始全部归零,所以我想如果我对两个文件进行布尔或运算,那么结果将是如果我没有犯错误的话 ddrescue 会输出什么?
这些文件不是彼此的延续(例如如何合并两个 ddrescue 图像?)因为我之前已经运行过ddrescue -n
,并且成功完成。即 IDTa.img 包含大部分数据,IDTa.iso 包含图像各处的分散块(这些块在 IDTa.img 中为零)。
有没有一种简单的 CLI 方法可以做到这一点?我可能可以用 C 语言做到这一点,但我很生疏!也可能是 Python 的一个很好的第一个练习,我从来没有抽出时间来学习它!尽管如此,如果已经存在某些东西,就不要特别想重新发明轮子。不太注重性能。
更新:(如果这是回复答案的错误位置,我深表歉意。“评论”选项似乎允许的字符太少,所以我在这里回复!)
我还尝试过使用 '--fill-mode=?' 进行 ddrescue作为上述问题的解决方案,但没有成功。这就是我所做的:
ddrescue --generate-mode -b 2048 -v /dev/sr1 IDTa.img IDTa.img.log
cp IDTa.img IDTa.img.backup
ddrescue '--fill-mode=?' -b 2048 -v IDTa.iso IDTa.img IDTa.img.log
为了检查,我查找了 IDTa.iso 有数据的第一个位置:
hexdump -C IDTa.iso |less
输出是:
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
001da800 00 00 01 ba 21 00 79 f3 09 80 10 69 00 00 01 e0 |....!.y....i....|
...
001db000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
...
我在 IDTa.img 中查找了 001da800:
hexdump -C IDTa.img |less
/001da800
输出:
001da800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
001db000 00 00 01 ba 21 00 7b 00 bf 80 10 69 00 00 01 e0 |....!.{....i....|
...
那么,位置 001da800 处的数据还没有从文件 IDTa.iso 复制到 IDTa.img 吗?
检查IDTa.img.log:
# Mapfile. Created by GNU ddrescue version 1.22
# Command line: ddrescue --fill-mode=? -b 2048 -v IDTa.iso IDTa.img IDTa.img.log
# Start time: 2021-06-28 13:52:39
# Current time: 2021-06-28 13:52:46
# Finished
# current_pos current_status current_pass
0x299F2000 + 1
# pos size status
0x00000000 0x00008000 ?
0x00008000 0x001D2800 +
0x001DA800 0x00000800 ?
0x001DB000 0x00049000 +
...
和现实检查:
diff -q IDTa.img IDTa.img.backup
返回没有区别。
更新2:
@Kamil 通过删除参数编辑了解决方案(见下文)--fill-mode=?
。看来工作了!
答案1
我认为这可以自己完成ddrescue
。你需要--generate-mode
。
当
ddrescue
使用选项调用时--generate-mode
,它在“生成模式”下运行,这与默认的“救援模式”不同。也就是说,在“生成模式”下ddrescue
不会拯救任何东西。它只是尝试生成mapfile
供以后使用。[…]
ddrescue
在某些情况下可以从 和 中生成近似mapfile
,infile
和 中的(部分)副本outfile
,这几乎与精确的 一样好mapfile
。它通过简单地假设包含全零的扇区没有被拯救来实现这一点。[…]
ddrescue --generate-mode infile outfile mapfile
(来源)
复制这两个图像,以防万一。如果您的文件系统支持 CoW-copy,则使用cp --reflink=always
每个图像几乎可以立即进行复制。
您需要确保两个图像的大小相同。如果其中之一较小,则应将其放大,即应附加零(可能是稀疏零)。此代码将自动执行此操作(truncate
必需):
( f1=IDTa.img
f2=IDTa.iso
s1="$(wc -c <"$f1")"
s2="$(wc -c <"$f2")"
if [ "$s2" -gt "$s1" ]; then
truncate -s "$s2" "$f1"
else
truncate -s "$s1" "$f2"
fi
)
(我使用了子 shell,因此变量会随之消失,而主 shell 不受影响。)
现在让该工具分析您的第一张图像并找出哪些扇区可能未获救:
ddrescue --generate-mode -b 2048 -v /dev/sr1 IDTa.img new_mapfile
注意new_mapfile
这里是一个新文件,不是你的IDTa.ddrescue.log
。请勿触摸IDTa.ddrescue.log
。
new_mapfile
生成后,其中的行应显示状态+
或?
,具体取决于相应的片段是否被视为“已救援”或“未尝试”。
IDTa.img
现在您想用来自 的数据填充据称“未尝试过”的块IDTa.iso
。下一个命令将修改IDTa.img
.
IDTa.img
通过读取数据来拯救所谓的“未尝试过”的块IDTa.iso
:
ddrescue -b 2048 -v IDTa.iso IDTa.img new_mapfile
现在,修改后的内容IDTa.img
和未修改的内容IDTa.ddrescue.log
应该和您没有犯错误一样好。
笔记:
- 可能发生了一些包含全零的扇区实际上被拯救的情况。
--generate-mode
将它们分类为?
.它们将充满从IDTa.iso
“徒劳”中获取的数据。这对于最终结果并不重要,因为它们在另一个文件中也全为零。 IDTa.iso
如果在整个过程中互换和 ,结果应该是相同的IDTa.img
(但请记住,如果这样做,结果将在 中IDTa.iso
)。所以有一个选择。我--generate-mode
将使用预计包含全零的扇区较少的文件,因为这应该最大限度地减少最后一个命令的工作量。- 该方法适用于常规文件
IDTa.iso
和IDTa.img
.相反,如果您有一个块设备,那么您工作之前的“随机”内容ddrescue
会干扰并破坏结果(因此,首先解决不同大小的潜在问题是没有意义的,这truncate
没有帮助)。 - 我在尝试拯救一个人时复制了你的错误后测试了该程序片状装置。