由于工作需要由于我特别喜欢折腾,所以我打算在 ArchLinux 上尝试使用 Btrfs。嗯,其实只要装系统的时候格成 btrfs 就好了。
Btrfs 是一个新型的写时拷贝 (copy on write, CoW) Linux 文件系统,已并入内核主线。以 GNU GPL 协议授权。
我的分区就非常无脑,500G 的盘,500M 给 EFI 启动分区,剩下的做 btrfs。
建立子卷
虽然 btrfs 提供了默认的根子卷,但是为了方便修改结构,wiki 上的建议是:
不使用顶层子卷 (ID=5) 挂载为根目录,可以更方便地修改子卷的布局结构。相反,可考虑创建新的子卷,然后挂载为
/
。
所以我们先建立一些基本的子卷:这里参照了依云博客讲的方案和OpenSUSE的方案。
# mount /dev/sda2 /mnt
# btrfs subvolume create @ #/
# btrfs subvolume create @home #/home
# btrfs subvolume create @log #/var/log
# btrfs subvolume create @tmp #/var/tmp
# btrfs subvolume create @cache #/var/cache
# btrfs subvolume create @swap #/swap
这样建子卷的目的:
@home
一般是用户数据,和根分区分开方便回滚。@log
用于日志的持久化,在使用快照启动系统时 (grub-btrfs
支持),需要/var/log
可写,但是快照本身是只读的,所以要分开建立,而且日志本身本身也没有回滚的必要。@tmp
、@cache
、@swap
,因为不要快照,所以分成了独立的子卷。以上这个方案是我踩了坑之后调整的,之前把
@var
单独分出一个子卷,出现的问题是:pacman
数据在/var/lib/pacman
下,如果对rootfs
执行回滚,那就会造成包管理的软件出现异常。因为没有同时回滚var
,也没有对var
进行快照。需要手动处理。
然后我们需要在 /swap
下建一个 swapfile
,但是需要注意,btrfs 里需要关闭 CoW 才能用 swapfile
,所以我们要这样操作:
# cd /path/to/swapfile
# truncate -s 0 ./swapfile
# chattr +C ./swapfile
# btrfs property set ./swapfile compression none
然后就能和原来的操作一样创建 swapfile
了。
挂载各个子卷,把分区表写到 /etc/fstab
都是装机经典操作了,这里不详细说了。主要是几个挂载参数,具体也可以看 btrfs(5) 的 man。后面安装的步骤就是 chroot
进去改个内核参数,装个boot-loader(GRUB),生成相关配置都是常规操作。
snapper 快照配置
Btrfs 可以使用 snapper 来维护快照,具体说明见 wiki。
首先要对 rootfs
建一个配置:
# snapper -c root create-config /
然后可以编辑 /etc/snapper/configs/root
来配置快照的策略,比如保留几个每小时快照,几个每日快照,等。
最后开启两个 systemd 的定时任务: snapper-timeline.timer
和 snapper-cleanup.timer
来执行定时快照和清理过期快照。当然如果要开机就要快照也可以开 snapper-boot.timer
。
最后,如果要在 bootloader (grub) 里通过只读快照启动(一般用不上,除非系统挂了不能启动),需要安装 grub-btrfs 开启 grub-btrfs.path
可以在每次快照后更新 grub 菜单。
休眠到 btrfs 中的 swapfile
然后我发现,装好的系统挂起是开箱即用的,但是这只是睡眠到 RAM,并不能完全断电,断电就GG了。如果要睡眠到硬盘就需要有 swap
,并进行一些配置。一些发行版应该在安装的时候会自动配置好。
非常不幸的是,我没有单独的 swap
分区,我把 swap
放在了 btrfs 的子卷里!于是这便是一个稍微有点 trick 的操作,wiki/Suspendand_hibernate(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)#%E4%BC%91%E7%9C%A0%E5%88%B0Btrfs%E4%B8%8A%E7%9A%84%E4%BA%A4%E6%8D%A2%E6%96%87%E4%BB%B6%E4%B8%AD) 上有详细的说明,需要改内核参数并配置 initramfs。