你好,我目前对使用 dd 命令后的结果有疑问。
[root@localhost sdb2]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 898M 0 898M 0% /dev
tmpfs 910M 0 910M 0% /dev/shm
tmpfs 910M 9.6M 901M 2% /run
tmpfs 910M 0 910M 0% /sys/fs/cgroup
/dev/mapper/centos-root 17G 1.3G 16G 8% /
/dev/sda1 1014M 151M 864M 15% /boot
tmpfs 182M 0 182M 0% /run/user/0
/dev/sdb1 4.8G 20M 4.6G 1% /root/sdb1
/dev/sdb2 4.8G 20M 4.6G 1% /root/sdb2
如您所见,我将 /dev/sdb 磁盘分成 2 个分区,并分别将它们挂载在 /root/sdb1 和 /root/sdb2 上。
我进入 /root/sdb1 并echo hello, world > test.txt
使用 输入 克隆了该分区dd if=/dev/sdb1 of=/dev/sdb2
。
然后我进入/root/sdb2查看test.txt文件是否存在,但是没有找到。
你为什么要这样做?我是不是忽略了什么?
我不知道为什么我没有立即看到 test.txt 的内容。请告诉我!
答案1
写入会/root/sdb1/test.txt
修改挂载在 上的文件系统/root/sdb1
。操作系统可能会缓存此修改并延迟写入底层块设备/dev/sdb1
。实际上,test.txt
当您从文件系统读取时 存在,但当您读取 时其内容可能存在也可能不存在/dev/sdb1
。
您dd
读取一个包含已安装用于写入的文件系统的设备。它不仅可能由于缓存而丢失一些数据;它还会在不同时刻读取文件系统的不同部分,如果在此期间文件系统被修改,那么无法保证所有部分都形成一个连贯的文件系统。
检查什么全景失败是。现实在任何给定时刻都是连贯的,但是通过在不同时刻拍摄部分图像并将它们连接在一起,您可能会得到错误的图像。文件系统也可能会发生这种情况。
但这不是您没有看到test.txt
的原因/root/sdb2
。
您dd
不仅可以从包含已安装以进行写入的文件系统的设备读取数据,还可以向包含已安装的文件系统的设备写入数据。操作系统很可能/root/sdb2
之前就知道了 的内容,这些信息已被缓存。写入 会/dev/sdb2
破坏设备上的旧文件系统,但由于它不涉及/root/sdb2
在文件系统级别写入,因此操作系统不会将此视为对已安装文件系统本身的更改,而是愉快地向您显示 的旧(缓存)内容,而/root/sdb2
无需从 重新读取任何内容/dev/sdb2
。
如果你继续使用/root/sdb2
,操作系统最终会写入 或读取/dev/sdb2
。然后:
写入对于 的旧文件系统的修改来说是有意义的,但是对于的现有
sdb2
副本而言,写入是没有意义的;因此,即使我们假设幸运地设法在某种连贯状态下复制了 的文件系统,使用仍然会破坏它;/dev/sdb1
/dev/sdb2
dd
sdb1
/root/sdb2
读取将提供来自(可能是“全景失败”)副本的操作系统数据
sdb1
,同时它期望与仍然安装在上的文件系统一致的数据/root/sdb2
;文件系统驱动程序可能会发现不一致并以只读方式重新安装,或者您可能会得到一些垃圾;一般来说,会发生奇怪的事情。
这就是为什么在块设备的文件系统被挂载用于写入时,您不应该复制块设备的内容;以及为什么在块设备的文件系统被挂载时,您不应该直接写入块设备。
上的文件系统/dev/sdb1
应该仍然没问题,但是的当前内容/dev/sdb2
很可能是一团糟(即使它类似于文件系统)。
正确的方法是umount /root/sdb1
和umount /root/sdb2
,然后复制(不一定与dd
)。最后,您就可以mount
再次使用这两个设备了*。
* 文件系统为 btrfs 时除外。克隆 btrfs 并在另一台设备也处于连接状态时尝试挂载原始设备或副本可能会导致数据丢失。请参阅这个答案以及那里的链接。