SDB:BTRFS
默认子卷
默认情况下,openSUSE 使用 Btrfs 和根分区的快照进行设置。快照允许您在应用更新后轻松回滚系统,或备份文件。可以使用 Snapper 轻松管理快照。
在使用快照回滚系统时,必须确保用户主目录、Web 和 FTP 服务器内容或日志文件等数据不会在回滚过程中丢失或被覆盖。这是通过在根文件系统上使用 Btrfs 子卷来实现的。子卷默认情况下从快照中排除。openSUSE 在安装过程中通过 YaST 提出的默认根文件系统设置包含以下子卷。由于以下原因,它们从快照中排除。
/boot/grub2/i386-pc, /boot/grub2/x86_64-efi, /boot/grub2/powerpc-ieee1275, /boot/grub2/s390x-emu
无法支持回滚引导加载程序配置。上述目录是特定于架构的。前两个目录存在于 AMD64/Intel 64 机器上,后两个目录存在于 IBM POWER 和 IBM z 系统上,分别。
/home
如果 /home 不位于单独的分区上,则将其排除以避免在回滚时丢失数据。
/opt
第三方产品通常安装到 /opt。将其排除以避免在回滚时卸载这些应用程序。
/root
root 用户的家目录也应在回滚期间保留
/srv
包含 Web 和 FTP 服务器的数据。将其排除以避免在回滚时丢失数据。
/tmp
所有包含临时文件和缓存的目录都从快照中排除。
/usr/local
此目录用于手动安装软件。将其排除以避免在回滚时卸载这些安装。
/var
此目录包含许多变量文件,包括日志、临时缓存、第三方产品在 /var/opt 中,并且是许多虚拟机镜像和数据库的默认位置。因此,创建此子卷以将所有这些变量数据从快照中排除,并禁用写入时复制创建。
旧 /var/* 子卷布局(2018 年 1 月之前)
在较旧的 *SUSE 发行版(SLE 12/Leap 42.x/和 2018 年 1 月之前安装的 Tumbleweed)中,默认的 btrfs 子卷布局将 /var 视为根文件系统的一部分,而是包含以下子卷在 /var 下
/var/opt
第三方产品通常安装到 /opt。将其排除以避免卸载这些应用程序
/var/tmp, /var/cache, /var/crash
所有包含临时文件和缓存的目录都从快照中排除。
/var/lib/libvirt/images
默认情况下,使用 libvirt 管理的虚拟机镜像的位置。排除以确保在回滚期间不会用旧版本替换虚拟机镜像。默认情况下,此子卷使用无复制写入选项创建。
/var/lib/mailman, /var/spool
包含邮件或邮件队列的目录从快照中排除,以避免在回滚后丢失邮件。
/var/lib/named
包含 DNS 服务器区域数据。从快照中排除,以确保在回滚后 DNS 服务器可以运行。
/var/lib/mariadb, /var/lib/mysql, /var/lib/pgqsl
这些目录包含数据库数据。默认情况下,这些子卷使用无复制写入选项创建。
/var/log
日志文件位置。从快照中排除,以便在损坏系统的回滚后进行日志文件分析。
压缩的 btrfs 文件系统
在 Leap 和 Tumbleweed 中,支持 Btrfs 文件系统的压缩。使用 compress 或 compress-force 选项并选择压缩算法,lzo 或 zlib(默认)。zlib 压缩具有更高的压缩率,而 lzo 更快且占用更少的 CPU 负载。例如
mount -o compress /dev/sdx /mnt
如果您创建文件、写入文件,并且压缩结果大于或等于未压缩的大小,Btrfs 将永远跳过该文件的未来写入操作的压缩。如果您不喜欢此行为,请使用 compress-force 选项。这对于具有一些初始不可压缩数据的文件很有用。
请注意,压缩仅对新文件有效。在挂载文件系统时使用 compress 或 compress-force 选项写入的文件不会被压缩。此外,具有 nodatacow 属性的文件永远不会对其扩展进行压缩
chattr +C FILE mount -o nodatacow /dev/sdx /mnt
关于加密,这与任何压缩无关。在将一些数据写入此分区后,打印详细信息
btrfs filesystem show /mnt
btrfs filesystem show /mnt
Label: 'Test-Btrfs' uuid: 62f0c378-e93e-4aa1-9532-93c6b780749d
Total devices 1 FS bytes used 3.22MiB
devid 1 size 2.00GiB used 240.62MiB path /dev/sdb1
如果希望永久生效,请将 compress 或 compress-force 选项添加到 /etc/fstab 配置文件中。例如
UUID=1a2b3c4d /home btrfs subvol=@/home,compress 0 0
检查可用空间
通常使用 df 命令检查文件系统使用情况。在 Btrfs 文件系统上,df 的输出可能会产生误导,因为除了原始数据分配的空间外,Btrfs 文件系统还会分配和使用空间来存储元数据。
因此,Btrfs 文件系统可能会报告空间不足,即使看起来仍然有大量可用空间。在这种情况下,用于元数据的空间已全部使用。使用以下命令检查 Btrfs 文件系统上已用和可用的空间
btrfs filesystem show
sudo btrfs filesystem show /
Label: 'ROOT' uuid: 52011c5e-5711-42d8-8c50-718a005ec4b3
Total devices 1 FS bytes used 10.02GiB
devid 1 size 20.02GiB used 13.78GiB path /dev/sda3
显示文件系统的总大小及其使用情况。如果最后一行中的这两个值匹配,则文件系统上的所有空间都已分配。
btrfs filesystem df
sudo btrfs filesystem df / Data, single: total=13.00GiB, used=9.61GiB System, single: total=32.00MiB, used=16.00KiB Metadata, single: total=768.00MiB, used=421.36MiB GlobalReserve, single: total=144.00MiB, used=0.00B
显示文件系统的已分配(总计)和已用空间的值。如果元数据的总计和已用值几乎相等,则所有元数据空间都已分配。
btrfs filesystem usage
sudo btrfs filesystem usage /Overall:
Device size: 20.02GiB
Device allocated: 13.78GiB
Device unallocated: 6.24GiB
Device missing: 0.00B
Used: 10.02GiB
Free (estimated): 9.63GiB (min: 9.63GiB)
Data ratio: 1.00
Metadata ratio: 1.00
Global reserve: 144.00MiB (used: 0.00B)
Data Metadata System
Id Path single single single Unallocated
-- --------- -------- --------- -------- -----------
1 /dev/sda3 13.00GiB 768.00MiB 32.00MiB 6.24GiB
-- --------- -------- --------- -------- -----------
Total 13.00GiB 768.00MiB 32.00MiB 6.24GiB
Used 9.61GiB 421.36MiB 16.00KiB显示类似于前两个命令组合在一起的数据。
有关更多信息,请参阅 man 8 btrfs-filesystem 和 https://btrfs.wiki.kernel.org/index.php/FAQ。
由于 Snapper 导致磁盘空间已满
如果 Snapper 正在为 Btrfs 文件系统运行,则“设备上没有剩余空间”问题通常是由于系统上存储了过多的快照数据造成的。
您可以从 Snapper 中删除一些快照,但是快照不会立即删除,并且可能无法释放您需要的那么多空间。
要从 Snapper 删除文件
- 打开终端控制台。
- 在命令行提示符下,输入 btrfs filesystem show,例如用户 $
sudo btrfs filesystem show /
Label: none uuid: 40123456-cb2c-4678-8b3d-d014d1c78c78 Total devices 1 FS bytes used 20.00GB devid 1 size 20.00GB used 20.00GB path /dev/sda3
- 输入用户 $此命令创建一个 zram 设备,我们将用作我们完整 btrfs 文件系统的临时、内存支持的存储。您可能需要用另一个整数替换
sudo zramctl /dev/zram0 --algorithm zstd --size "$(($(grep -Po 'MemTotal:\s*\K\d+' /proc/meminfo)/2))KiB"/dev/zram0中的 0,如果您已经有/dev/zram0设备。 - 输入用户 $这将我们的 zram 设备添加到完整的 btrfs 文件系统
sudo btrfs device add /dev/zram0 / - 列出 Snapper 中的快照。输入用户 $
sudo snapper -c root list - 从 Snapper 删除一个或多个快照。输入用户 $确保首先删除最旧的快照。快照越旧,它占用的磁盘空间就越多。
sudo snapper -c root delete snapshot_number(s) - 从文件系统中删除 zram 设备用户 $
sudo btrfs device remove /dev/zram0 / - 从您的系统中删除 zram 设备用户 $
sudo zramctl -r /dev/zram0
如何修复损坏/无法挂载的 btrfs 文件系统
以下是任何重大 btrfs 文件系统问题的推荐步骤,尤其是当它无法挂载时。阅读 dmesg 或 syslog 可能会帮助您确定可以跳过哪些步骤来修复特定问题,但初始步骤通常无论如何都很有用,因为 btrfs scrub 是一个非常安全的修复工具。
- 启动到合适的替代系统,例如救援 shell、openSUSE 的不同安装、liveCD 或 openSUSE 安装 DVD。您正在运行的 openSUSE 版本的安装 DVD 通常是一个不错的选择,因为它肯定会使用相同的内核/btrfs 版本。最新的 Tumbleweed 磁盘可能更好,因为它将包含较新的内核/btrfs
- 转到合适的控制台并确保您执行以下操作,以 root 身份
- 尝试将您的分区挂载到 /mnt,只是为了确认它确实已损坏
mount /dev/sda1 /mnt
- 如果它挂载 - 您确定它已损坏吗?如果是 - 运行
btrfs scrub start /mnt
以 scrub 系统,并
btrfs scrub status /mnt
以监控它
- 如果它没有挂载,请尝试 scrub 该设备,以防万一有效
btrfs scrub start /dev/sda1
和
btrfs scrub status /dev/sda1
进行监控。完成后,尝试挂载,如果成功,则已修复。
- 如果 scrubbing 不是一个选项或无法解决问题
那么尝试 mount -o usebackuproot
mount -o usebackuproot /dev/sda1 /mnt
- 运行“btrfs check <device>”
btrfs check /dev/sda1
这无济于事,但请将其日志保存在某个地方,它对错误报告很有用。
- 认真考虑运行“btrfs restore <device> <somewhereto copy data>”
btrfs restore /dev/sda1 /mnt/usbdrive
这不会修复任何问题,但它会扫描文件系统并恢复它能恢复的一切到已挂载的设备上。如果你的 btrfs 问题实际上是由硬件故障而不是 btrfs 故障引起的,这尤其有用。
- 运行 "btrfs rescue super-recover <设备>"
btrfs rescue super-recover /dev/sda1
然后尝试正常挂载设备。如果成功,停止操作。
- 运行 "btrfs rescue zero-log <设备>"
btrfs rescue zero-log /dev/sda1
然后尝试正常挂载设备。如果成功,停止操作。
- 运行 "btrfs rescue chunk-recover <设备>"
btrfs rescue chunk-recover /dev/sda1"
这将会花费很长时间。然后尝试正常挂载设备。如果成功,停止操作。
- 如果你之前没有运行,现在务必运行 "btrfs restore <设备> <复制数据的目标位置>"
btrfs restore /dev/sda1 /mnt/usbdrive
- 此时不使用 btrfs restore,而继续尝试修复,意味着你面临极高的数据丢失风险。 建议使用 btrfs restore 尽可能地恢复数据,然后再继续。
- 现在,只有现在,尝试 btrfsck,即 "btrfs check --repair <设备>"
btrfs check --repair /dev/sda1
如何在 openSUSE/btrfs 上手动重新安装 grub
重新安装 grub 的一般方法是三个步骤
- 挂载根文件系统并绑定挂载虚拟系统文件夹 (/proc, /sys, /dev)
- chroot 到上面挂载的根 FS
- 发出适当的 grub 命令来重新安装它。
在 openSUSE/Tumbleweed 上,第一步比较棘手,因为根 FS 和一些子文件夹是子卷。
本节的目的是向你展示一个逐步重新安装 grub 的过程,重点是上述第一步,假设标准的 openSUSE 磁盘布局。
启动
首先使用 openSUSE Leap 或 Tumbleweed 安装介质(在 USB 存储设备上)启动计算机。
使用“救援系统”菜单选项获取完整的 root shell。 在 openSUSE 安装介质上,它位于“更多...”菜单下。
识别启动磁盘和分区
完成 USB 启动后,你将获得一个交互式 root shell,以发出将 fdisk 恢复使用的命令。
第一件事是识别你安装了 openSUSE 的磁盘和分区。为此,你可以使用 lsblk -f 来列出当前磁盘驱动器、分区和文件系统类型。 查找 FSTYPE 为 btrfs。
lsblk -f NAME FSTYPE FSVER ... sda ... |-sda1 ntfs ... |-sda2 ntfs ... |-sda3 ntfs ... `-sda4 btrfs ...
基于以上信息,看起来 openSUSE 磁盘和分区是/dev/sda4.
上面的示例来自一个磁盘,其中另一个操作系统与 openSUSE/Tumbleweed 双引导安装。
你的 openSUSE/Tumbleweed 安装可能位于不同的分区号,甚至安装在不同的磁盘上。挂载磁盘
下一步是挂载该分区以访问它。 在挂载之前,我们需要一个文件夹作为挂载点,我们将在/mnt/volume.
mkdir /mnt/volume mount /dev/sdXn /mnt/volume # use the correct disk and partition you got above.
此时查看/mnt/volume
ls /mnt/volume .snapshots bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
如果输出看起来像上面那样,你找到了正确的磁盘/分区来挂载。 如果没有,请立即使用 umount /mnt/volume 卸载 FS 以避免弄乱它,并再次查看 lsblk -f 的输出
- 检查当前可用的子卷
以/mnt/volume挂载 FS 的方式不适合安装 grub。 由于许多系统文件夹实际上是 btrfs 子卷,我们需要以适当的方式挂载这些子卷,为此我们需要知道子卷的名称。
要列出/mnt/volume中的所有子卷名称,请使用以下命令
btrfs subvolume list /mnt/volume ID 256 gen 31 top level 5 path @ ID 257 gen 6421 top level 256 path @/var ID 258 gen 6065 top level 256 path @/usr/local ID 259 gen 6065 top level 256 path @/srv ID 260 gen 6417 top level 256 path @/root ID 261 gen 6135 top level 256 path @/opt ID 262 gen 6421 top level 256 path @/home ID 263 gen 6016 top level 256 path @/boot/grub2/x86_64-efi ID 264 gen 6016 top level 256 path @/boot/grub2/i386-pc ID 265 gen 6327 top level 256 path @/.snapshots ID 266 gen 6420 top level 265 path @/.snapshots/1/snapshot ... # more lines follows...
Take a note of pairs of <ID_number>/path for each relevant path in the following list:
- @
- @/var
- @/boot/grub2/x86_64-efi
- @/boot/grub2/i386-pc
- 创建另一个挂载点到根 FS 并挂载子卷
现在我们将以适当的文件夹挂载上述每个子卷
mkdir /mnt/my-root mount /dev/sdXn -o subvolid=<ID for path @> /mnt/my-root mount /dev/sdXn -o subvolid=<ID for path @/var> /mnt/my-root/var mount /dev/sdXn -o subvolid=<ID for path @/boot/grub2/x86_64-efi> /mnt/my-root/boot/grub2/x86_64-efi mount /dev/sdXn -o subvolid=<ID for path @/boot/grub2/i386-pc> /mnt/my-root/boot/grub2/i386-pc
- 绑定挂载
我们需要当前正在运行的系统的虚拟文件夹/proc, /sys和/dev。
mount /proc -o bind /mnt/my-root/proc mount /sys -o bind /mnt/my-root/sys mount /dev -o bind /mnt/my-root/dev
更改 root 并安装 grub
这是最后一步。 这里没有什么新的。 它与你可能在互联网上阅读的其他 FS 类型(如 ext4)没有区别。 运行 chroot 到/mnt/my-root的全新挂载的 FS,然后运行 update-bootloader --reinit 或/和 grub2-install
chroot /mnt/my-root update-bootloader --reinit # or grub2-install