我有一个列出了 418 个坏扇区mapfile
的生成器ddrescue
,其中每行如下所示(减号表示坏块):
Position Size
0x1CC7C68000 0x00001000 -
通过将字节位置转换为分区相对扇区号,我可以用来debugfs
查询索引节点号,然后找到损坏文件的路径。对于近 2000 个坏块,手动执行此操作是不可行的,因此我想自动执行此操作,有没有办法编写脚本debugfs
来在文件系统上执行一系列命令?
以下是我目前正在执行的获取损坏扇区的文件名的操作:
中的位置
ddrescue
mapfile
以相对于磁盘开头的字节为单位。首先,我通过除以 512 将位置转换为扇区号,然后减去分区的起始扇区位置:第一个扇区的分区:91914240 坏块位置:0x1CC7C68000 十进制:123610759168 绝对扇区位置:123610759168 / 512 = 241427264 分区上的相对块位置:241427264 - 91914240 = 149513024
所以坏扇区是149513024
相对于分区开始的,使用debugfs
我现在可以找到索引节点:
$ debugfs
debugfs: open /dev/sdd3
debugfs: icheck 149513024
Block Inode number
149513024 1183169
debugfs: ncheck 1183169
Inode Pathname
1183169 /username/foo/bar/baz
我想自动化这个过程,这样我就可以将块位置列表传递给debugfs
,将这些块解析为 inode,过滤 inode 以排除未映射的 inode,然后用于ncheck
解析剩余 inode 的路径名。这可以通过 debugfs 和一些 shell 脚本实现吗?
答案1
我相信我已经找到了解决我的问题的方法。但是,我仍然很好奇是否有人可以提出更优雅的解决方案或者可能在我的解决方案中发现错误。
事实证明,我可以写入 的 stdin debugfs
,因此我只需要为 生成一系列命令debugfs
,即可分析 的输出ddrescue
。
以下 bash 脚本假定mapfile.ddrescue
当前目录中存在一个名为 的文件,该文件是由ddrescue
.
for line in \
$(cat mapfile.ddrescue | \
grep -e "-$" | \
awk -F" " '{print $1}' | \
awk -F"0x" '{print $2}'); \
do \
position=$(( 16#$line / 512 - 91914240 )); \
result="$result $position"; \
done; \
echo -e "open /dev/sdd3\nicheck $result\nquit\n" | sudo debugfs
该脚本的作用如下:
- 我解析了我命名的
mapfile
from 。ddrescue
mapfile.ddrescue
- 我对其进行过滤以仅保留以连字符结尾的行。这些是有坏块的位置。
- 我使用 awk 在空白处分割并打印第一个标记,即位置。这将包含一个十六进制数字,例如 0x34A933F000。
- 我删除了
Ox
前缀。 - 调用手返回的结果
$(...)
作为 for 循环的输入,因此 line 将始终包含一个位置。 - 我使用
$(( ... ))
表达式对位置进行数学计算,将位置除以 512(例如每个扇区的字节数)并减去分区起始位置(在我的例子中为 )91914240
。这给出了相对于分区开始的扇区位置。 - 我将每个位置连接到一个空格分隔的列表中,该列表存储在
$result
. - 最后,我生成以换行符分隔的命令列表,将其通过管道传输到
debugfs
使用 sudo 运行的命令的标准输入。该命令打开设备(在我的例子中/dev/sdd3
)。然后它icheck
在 上运行$result
并从 退出debugfs
。
当我运行这个脚本时,debugfs
花了很长时间才找到inodes
这些块的所有内容,在我的例子中,它似乎挂起了几分钟,直到打印输出。
脚本完成后,我将结果复制到文本文件中并进行分析。幸运的是,大多数扇区都指向未分配的块,而其余扇区中的大多数都指向相同的几个数字inode
。删除行<block not found>
并删除重复项后,只剩inodes
下四行,我可以debugfs
使用手动检查ncheck
。这给了我四个文件路径,这些是我现在将尝试从备份恢复的文件。
背景
我最初是dd
想将 256GB SSD 的内容复制到更大的 SSD。dd
在最后一个分区的大约 45/185 GB 处因 I/O 错误而中止。然而,ddrescue
我可以拯救99.99%驱动器的。最后,通过上述解决方案,我能够检查剩余的 1700kb 或 418 个坏区属于哪些文件,并发现只有 4 个文件损坏。这充分增加了我对恢复数据的信任,因为我现在知道哪些文件已损坏并且可以从较旧的备份中恢复它们。
答案2
今天我的 rpi3b+ SD 卡坏了之后不得不这样做。我最终编写了一个 python 脚本,执行您在上面的 bash 脚本中所做的操作,只不过它会自动吐出文件路径。你可以在这里查看:https://github.com/zkrx/rescue2path
在此解决方案中,我还检查尚未抓取的数据块(“/”)。在这里刮了很长时间,我就在刮完之前停了下来。
Arch wiki 中的这个条目特别有用:https://wiki.archlinux.org/index.php/Identify_damaging_files