![为什么dd命令可以恢复使用shred删除的文件?](https://linux22.com/image/226058/%E4%B8%BA%E4%BB%80%E4%B9%88dd%E5%91%BD%E4%BB%A4%E5%8F%AF%E4%BB%A5%E6%81%A2%E5%A4%8D%E4%BD%BF%E7%94%A8shred%E5%88%A0%E9%99%A4%E7%9A%84%E6%96%87%E4%BB%B6%EF%BC%9F.png)
我使用 找到了文件的索引节点ls -li
。然后我在磁盘上找到了文件的起始块。我使用该命令将该块的内容复制到另一个目录dd
。然后我使用实用程序粉碎了该文件shred
:shred -uvz -n=10 file1.txt
。我dd
再次运行相同的命令。文件已恢复。文件被粉碎后我应该得到 00000 。我缺少什么?
在第二次迭代中,我shred -vz -n=10 file2.txt
改为运行,这不会删除文件。按照与之前相同的步骤,我再次能够使用命令dd
和块位置恢复原始文件。然而,粉碎文件的内容为 00000,如 所示hexdump file2.txt
。我缺少什么?
答案1
文件系统应该具有对其块设备的独占访问权。dd
在安装文件系统时,您不应该直接在块设备上使用。
当您使用dd
(或任何其他用户空间程序)直接从块设备读取字节时,该读取会被缓存。如果再次重复dd
,它将从缓存中读取数据。
不幸的是,写入数据(通过文件系统)不会更新此缓存。因此,您会遇到缓存中的数据不反映磁盘上的数据的情况。
发生这种情况的另一个例子是 TRIM。如果缓存了任何块设备数据,您仍然可以从缓存中获取数据,即使 TRIM 已将其删除。这就是为什么测试 TRIM 时必须删除缓存。
使用一些文件创建一个文件系统:
# truncate -s 10G filesystem.img
# mkfs.ext4 filesystem.img
# losetup --find --show filesystem.img
/dev/loop1
# mount /dev/loop1 loop/
# for n in {000..100} ; do yes $n | dd bs=1M count=1 iflag=fullblock of=loop/$n; done 2> /dev/null
# sync
检查文件内容和物理偏移量:
# hexdump -C loop/042
00000000 30 34 32 0a 30 34 32 0a 30 34 32 0a 30 34 32 0a |042.042.042.042.|
*
00100000
# filefrag -ve loop/042
Filesystem type is: ef53
File size of loop/042 is 1048576 (256 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 255: 44800.. 45055: 256: last,eof
loop/042: 1 extent found
从块设备读取:
# dd bs=4096 skip=44800 count=256 if=/dev/loop1 | hexdump -C
00000000 30 34 32 0a 30 34 32 0a 30 34 32 0a 30 34 32 0a |042.042.042.042.|
*
00100000
撕碎:
# shred -v -n 1 loop/042
shred: loop/042: pass 1/1 (random)...
从块设备读取(缓存):
# dd bs=4096 skip=44800 count=256 if=/dev/loop1 | hexdump -C
00000000 30 34 32 0a 30 34 32 0a 30 34 32 0a 30 34 32 0a |042.042.042.042.|
*
00100000
从块设备读取 ( iflag=nocache
):
# dd bs=4096 skip=44800 count=256 if=/dev/loop1 iflag=nocache | hexdump -C
00000000 30 34 32 0a 30 34 32 0a 30 34 32 0a 30 34 32 0a |042.042.042.042.|
*
00100000
# dd bs=4096 skip=44800 count=256 if=/dev/loop1 iflag=nocache | hexdump -C | head
00000000 59 c2 d8 d4 5a 02 35 15 a1 fb f1 07 ae 53 59 99 |Y...Z.5......SY.|
00000010 5b 47 4f fc 2c e7 d3 db 10 70 c6 72 3e 6f 0b 05 |[GO.,....p.r>o..|
00000020 f5 07 c6 f7 95 64 8b a2 4e 7f 32 4f 0c b1 a3 32 |.....d..N.2O...2|
00000030 18 b5 99 7d 7d 6e 6d d6 b9 36 77 af 30 02 ba 23 |...}}nm..6w.0..#|
00000040 f5 55 a5 b7 01 51 cd 5b 64 c9 29 1f f6 48 23 6c |.U...Q.[d.)..H#l|
dd iflag=nocache
仅从缓存中删除数据后从缓存中读取它,因此必须执行两次才能看到新数据。或者,您可以使用sync; echo 3 > /proc/sys/vm/drop_caches
删除所有缓存或使用直接 I/O 碰碰运气。