我想以编程方式在Linux中制作实时文件系统的快照,最好使用LVM。我不想卸载它,因为我打开了很多文件(我最常见的情况是我有一个繁忙的桌面,有很多程序)。
据我所知,由于内核缓冲区和一般文件系统活动,磁盘上的数据可能处于某种或多或少的未定义状态。
有没有办法“原子地”卸载FS,制作LVM快照并将其挂载?如果操作系统将阻止所有活动几秒钟来执行此任务,那就没问题了。或者也许某种原子“同步+快照”?内核通话?
我不知道是否有可能......
答案 0 :(得分:11)
对于大多数Linux文件系统,您不应该做任何事情。它应该在你没有任何努力的情况下工作。快照命令本身使用正在快照的卷搜寻已挂载的文件系统,并调用一个特殊的挂钩,以一致的可挂载状态检查它们并以原子方式执行快照。
早期版本的LVM带有一组VFS锁定补丁,可以修补各种文件系统,以便可以为快照检查点。但是新内核应该已经内置到大多数Linux文件系统中。
此intro on snapshots声称同样多。
还有一点研究表明,对于2.6系列中的内核,ext系列文件系统应该都支持这一点。 ReiserFS也可能。如果我知道btrfs的人,那个人可能也会这样做。
答案 1 :(得分:4)
我知道RedHat Enterprise,Fedora和CentOS中的ext3和ext4会在创建LVM快照时自动检查点。这意味着安装快照永远不会有任何问题,因为它总是干净的。
我相信 XFS具有相同的支持。我不确定其他文件系统。
答案 2 :(得分:3)
这取决于您使用的文件系统。使用XFS,您可以使用xfs_freeze -f
来同步和冻结FS,并使用xfs_freeze -u
再次激活它,这样您就可以从冻结的卷创建快照,这应该是一个保存状态。
答案 3 :(得分:1)
我不确定这是否适合您,但您可以将文件系统重新安装为只读。 mount -o remount,ro /lvm
(或类似的东西)可以解决问题。完成快照后,您可以使用mount -o remount,rw /lvm
重新安装读写。
答案 4 :(得分:1)
有没有办法“原子地”卸载FS,制作LVM快照并将其挂载?
即使文件系统不在LVM卷上,也可以对挂载的文件系统进行快照。如果文件系统在LVM上,或者它有内置的快照工具(例如btrfs或ZFS),那么请改用它们。
以下说明相当低级,但如果您希望能够对不在LVM卷上的文件系统进行快照,并且无法将其移动到新的LVM卷,则它们非常有用。但是,他们不是为了胆小的人:如果你犯了错误,你可能会破坏你的文件系统。请务必参阅the official documentation和dmsetup
手册页,三重检查您正在运行的命令,备份!
Linux内核有一个很棒的工具叫做Device Mapper,它可以做很好的事情,比如创建块设备,这些设备是其他块设备的“视图”,当然还有快照。这也是LVM在引擎盖下使用的重要工具。
在下面的示例中,我假设您要快照/home
,这是位于/dev/sda2
的ext4文件系统。
首先,找到安装分区的设备映射器设备的名称:
# mount | grep home
/dev/mapper/home on /home type ext4 (rw,relatime,data=ordered)
此处,设备映射器设备名称为home
。如果块设备的路径不以/dev/mapper/
开头,则需要创建设备映射器设备,并重新安装文件系统以使用该设备而不是HDD分区。你只需要这样做一次。
# dmsetup create home --table "0 $(blockdev --getsz /dev/sda2) linear /dev/sda2 0"
# umount /home
# mount -t ext4 /dev/mapper/home /home
接下来,获取块设备的设备映射表:
# dmsetup table home
home: 0 3864024960 linear 9:2 0
您的电话号码可能会有所不同。设备目标应为linear
;如果不是,您可能需要特别考虑。如果最后一个数字(起始偏移量)不为0,则需要创建一个中间块设备(与当前的设备具有相同的表)并将其用作基础而不是/dev/sda2
。
在上面的示例中,home
正在使用带有linear
目标的单条目表。您需要将此表替换为使用snapshot
目标的新表。
设备映射器为快照提供了三个目标:
snapshot
目标,用于保存对指定COW设备的写入。 (请注意,即使它被称为快照,术语也会产生误导,因为快照是可写的,但底层设备将保持不变。)
snapshot-origin
目标,它将写入发送到底层设备,但也将写入覆盖的旧数据发送到指定的COW设备。
通常情况下,您需要home
snapshot-origin
个目标,然后在其上创建一些snapshot
个目标。这就是LVM的作用。但是,更简单的方法是直接创建snapshot
目标,这将在下面显示。
无论您选择哪种方法,都不能写入底层设备(/dev/sda2
),否则快照会看到文件系统的损坏视图。因此,作为预防措施,您应该将基础块设备标记为只读:
# blockdev --setro /dev/sda2
这不会影响由它支持的设备映射设备,因此如果您已经/home
重新安装/dev/mapper/home
,则不会产生明显的影响。
接下来,您需要准备COW设备,该设备将存储自快照制作以来的更改。这必须是块设备,但可以由稀疏文件支持。如果你想使用例如稀疏文件32GB:
# dd if=/dev/zero bs=1M count=0 seek=32768 of=/home_cow
# losetup --find --show /home_cow
/dev/loop0
显然,稀疏文件不应该在你正在快照的文件系统上:)
现在您可以重新加载设备的表并将其转换为快照设备:
# dmsetup suspend home && \
dmsetup reload home --table \
"0 $(blockdev --getsz /dev/sda2) snapshot /dev/sda2 /dev/loop0 PO 8" && \
dmsetup resume home
如果成功,则/home
的新写入现在应记录在/home_cow
文件中,而不是写入/dev/sda2
。确保监视COW文件的大小以及文件系统上的可用空间,以避免耗尽COW空间。
一旦您不再需要快照,您可以合并它(将COW文件中的更改永久提交到底层设备),或丢弃它。
要合并它:
将表替换为snapshot-merge
目标而不是snapshot
目标:
# dmsetup suspend home && \
dmsetup reload home --table \
"0 $(blockdev --getsz /dev/sda2) snapshot-merge /dev/sda2 /dev/loop0 P 8" && \
dmsetup resume home
接下来,监视合并的状态,直到合并所有非元数据块:
# watch dmsetup status home
...
0 3864024960 snapshot-merge 281688/2097152 1104
注意末尾的3个数字(X / Y Z)。当X = Z时,合并完成。
接下来,再次使用线性目标替换表格:
# dmsetup suspend home && \
dmsetup reload home --table \
"0 $(blockdev --getsz /dev/sda2) linear /dev/sda2 0" && \
dmsetup resume home
现在您可以拆除循环设备:
# losetup -d /dev/loop0
最后,您可以删除COW文件。
# rm /home_cow
要放弃快照,请卸载/home
,按照上述步骤3-5操作,然后重新安装/home
。尽管Device Mapper允许您在不卸载/home
的情况下执行此操作,但它没有意义(因为内存中正在运行的程序状态将不再对应于文件系统状态),并且它可能会损坏您的文件系统。
答案 5 :(得分:0)