前言
在之前的如何在Gentoo上优雅的吃ZFS这篇文章中我们上了ZFS,但是没有给swap单独的一个分区,后来在使用中确实遇到了内存不够的情况。直接在系统里面丢swapfile是不合理的,最好是有个单独的分区给swap,所以还是要再来一次分区备份和恢复系统:)
我这里的思路是这样子:
- 创建ZFS池(建立在扩展的USB上)
- 创建快照
- 发送快照
- 重建分区和ZFS
- 恢复快照
- 更改fstab和Bootload信息
- 重启
- 定时任务
准备环境
这次需要准备物品如下:
- 主电脑(也就是我们目标备份的这台)
- 一个USB启动设备(需要有ZFS工具)
- 一个备份设备
- 另外一台电脑(推荐,有问题的时候可以通过这台电脑查询问题。)
创建备份ZFS池
首先进入livecd,查看设备:
输出如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| Disk /dev/nvme0n1: 1.86 TiB, 2048408248320 bytes, 4000797360 sectors
Disk model: KXG50PNV2T04 KIOXIA
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: AFD9539F-0A10-4184-9E73-20652BA3D677
Device Start End Sectors Size Type
/dev/nvme0n1p1 2048 264191 262144 128M Linux filesystem
/dev/nvme0n1p2 264192 4000797326 4000533135 1.9T Linux filesystem
Disk /dev/sda: 233.76 GiB, 251000193024 bytes, 490234752 sectors
Disk model: MAC3E
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/sdc: 57.81 GiB, 62075699200 bytes, 121241600 sectors
Disk model: DataTraveler 3.0
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 7EE1FFAC-4072-46B8-885E-A7EA3F9C70CF
Device Start End Sectors Size Type
/dev/sdc1 64 5735483 5735420 2.7G Microsoft basic data
/dev/sdc2 5735484 5745435 9952 4.9M EFI System
/dev/sdc3 5745436 5746035 600 300K Microsoft basic data
/dev/sdc4 5746688 121241536 115494849 55.1G Linux filesystem
|
这里的设备分别为:
物理位置 | 说明 |
---|
/dev/nvme0n1 | 系统盘 |
/dev/sda | 备份盘 |
/dev/sdc | 启动盘 |
首先在备份盘上创建一个分区(分配所有空间到这个分区上):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| fdisk /dev/sda
Welcome to fdisk (util-linux 2.36).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x108318f9.
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p):
Using default response p.
Partition number (1-4, default 1):
First sector (2048-490234751, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-490234751, default 490234751):
Created a new partition 1 of type 'Linux' and of size 233.8 GiB.
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
|
查看硬盘ID
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| ls -l /dev/disk/by-id
total 0
lrwxrwxrwx 1 root root 13 Feb 27 14:37 nvme-KXG50PNV2T04_KIOXIA_Y9IS103FTHDM -> ../../nvme0n1
lrwxrwxrwx 1 root root 15 Feb 27 14:37 nvme-KXG50PNV2T04_KIOXIA_Y9IS103FTHDM-part1 -> ../../nvme0n1p1
lrwxrwxrwx 1 root root 15 Feb 27 14:37 nvme-KXG50PNV2T04_KIOXIA_Y9IS103FTHDM-part2 -> ../../nvme0n1p2
lrwxrwxrwx 1 root root 13 Feb 27 14:37 nvme-eui.000000000000001000080d0200600f01 -> ../../nvme0n1
lrwxrwxrwx 1 root root 15 Feb 27 14:37 nvme-eui.000000000000001000080d0200600f01-part1 -> ../../nvme0n1p1
lrwxrwxrwx 1 root root 15 Feb 27 14:37 nvme-eui.000000000000001000080d0200600f01-part2 -> ../../nvme0n1p2
lrwxrwxrwx 1 root root 9 Feb 27 14:53 usb-ACASIS_MAC3E_000000000001-0:0 -> ../../sda
lrwxrwxrwx 1 root root 10 Feb 27 14:53 usb-ACASIS_MAC3E_000000000001-0:0-part1 -> ../../sda1
lrwxrwxrwx 1 root root 9 Feb 27 14:37 usb-APPLE_SD_Card_Reader_000000000820-0:0 -> ../../sdb
lrwxrwxrwx 1 root root 9 Feb 27 14:37 usb-Kingston_DataTraveler_3.0_60A44C3D7ECDBF1089740049-0:0 -> ../../sdc
lrwxrwxrwx 1 root root 10 Feb 27 14:37 usb-Kingston_DataTraveler_3.0_60A44C3D7ECDBF1089740049-0:0-part1 -> ../../sdc1
lrwxrwxrwx 1 root root 10 Feb 27 14:37 usb-Kingston_DataTraveler_3.0_60A44C3D7ECDBF1089740049-0:0-part2 -> ../../sdc2
lrwxrwxrwx 1 root root 10 Feb 27 14:37 usb-Kingston_DataTraveler_3.0_60A44C3D7ECDBF1089740049-0:0-part3 -> ../../sdc3
lrwxrwxrwx 1 root root 10 Feb 27 14:37 usb-Kingston_DataTraveler_3.0_60A44C3D7ECDBF1089740049-0:0-part4 -> ../../sdc4
|
usb-ACASIS_MAC3E_000000000001-0:0-part1
这里就是我们所需要的硬盘ID,我们使用这个来创建备份池子:
1
| zpool create -f -o ashift=12 -o cachefile=/etc/zfs/zpool.cache -O compression=lz4 -O xattr=sa -O relatime=on -O acltype=posixacl -O dedup=off -m none -R /mnt/backup backup /dev/disk/by-id/usb-ACASIS_MAC3E_000000000001-0:0-part1
|
创建快照
首先导入原来的zpool
给之前的系统创建一个快照:
1
| sudo zfs snapshot rock/os/gentoo@2021-02-27-0000-01-install
|
查看
1
2
| zfs list -r -t snapshot -o name,creation rock/os/gentoo
rock/os/gentoo@2021-02-27-0000-01-install Sat Feb 27 14:16 2021
|
发送快照
我们需要打开原来的rock/os/gentoo
数据集
但是首先要设置一下挂载点:
1
| zfs set mountpoint=/mnt/gentoo rock/os/gentoo
|
打开rock/os/gentoo
数据集
发送快照到backup/os/gentoo
1
| zfs send rock/os/gentoo@2021-02-27-0000-01-install | zfs recv backup/2021-02-27-0000-01-backup
|
这个会花很长的时间,取决于你使用的接口速度,可以通过这条命令查看io情况:
这条命令是查看所有的zpool
io情况,2秒刷新一次。
创建分区
当备份完成之后我们要重建分区,这里首先把原来的分区卸载然后干掉:
1
2
| zfs unmount rock/os/gentoo
zpool destroy rock
|
备份/boot
分区的内容
设置挂载点
1
| zfs set mountpoint=/mnt/backup backup/2021-02-27-0000-01-backup
|
备份
1
2
3
| mkdir -pv /mnt/boot
mount -v /dev/nvme0n1p1 /mnt/boot
cp -rv /mnt/boot/* /mnt/backup/boot/
|
重新分区:
这次的分区如下表:
分区 | 文件系统 | 大小 |
---|
/dev/nvme0n1p1 | fat32 | 128M |
/dev/nvme0n1p2 | swap | 64G |
/dev/nvme0n1p3 | ZFS | ALL |
重建ZFS
创建ZFS池:
1
| zpool create -f -o ashift=12 -o cachefile=/etc/zfs/zpool.cache -O compression=lz4 -O xattr=sa -O relatime=on -O acltype=posixacl -O dedup=off -m none -R /mnt/gentoo rock /dev/disk/by-id/nvme-eui.000000000000001000080d0200600f01-part3
|
创建rock/os
数据集:
1
| zfs create -o mountpoint=none -o canmount=off -o encryption=on -o keyformat=passphrase rock/os
|
恢复快照
卸除挂载:
1
| zfs umount backup/2021-02-27-0000-01-backup
|
现在就可以恢复快照了:
1
| zfs send backup/2021-02-27-0000-01-backup | zfs recv -F -x encryption rock/os/gentoo
|
更改fstab和Bootload信息
进入chroot
首先更改挂载分区设置:
1
| zfs set mountpoint=/mnt/gentoo rock/os/gentoo
|
拷贝ZFS池缓存文件
1
2
| mkdir -pv /mnt/gentoo/etc/zfs
cp -v /etc/zfs/zpool.cache /mnt/gentoo/etc/zfs
|
拷贝网络的DNS
1
| cp --dereference /etc/resolv.conf /mnt/gentoo/etc/
|
挂载必要的文件系统
1
2
3
4
5
| mount --types proc /proc /mnt/gentoo/proc
mount --rbind /sys /mnt/gentoo/sys
mount --make-rslave /mnt/gentoo/sys
mount --rbind /dev /mnt/gentoo/dev
mount --make-rslave /mnt/gentoo/dev
|
我们不是在官方的Livecd下面还需要执行:
1
2
3
| test -L /dev/shm && rm /dev/shm && mkdir /dev/shm
mount --types tmpfs --options nosuid,nodev,noexec shm /dev/shm
chmod 1777 /dev/shm
|
进入chroot
1
2
3
| chroot /mnt/gentoo /bin/bash
source /etc/profile
export PS1="(chroot) $PS1"
|
修改fstab文件
修改fstab文件:
1
2
3
| /dev/nvme0n1p1 /boot vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 0 2
# /dev/nvme0n1p2
/dev/nvme0n1p2 none swap defaults,pri=-2 0 0
|
bootload和内核
挂载分区
1
| mount -v /dev/nvme0n1p1 /boot
|
安装bootload
1
| grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=Gentoo
|
修改grub
配置文件
1
| GRUB_CMDLINE_LINUX="dozfs root=ZFS=rock/os/gentoo"
|
安装内核和initramfs
1
2
3
| cd /usr/src/linux
make install
genkernel initramfs --zfs --compress-initramfs
|
生成grub配置文件:
1
| grub-mkconfig -o /boot/grub/grub.cfg
|
重启
退出当前的chroot环境:
重启系统
重启之后第一次可能还是没办法正常进入系统,需要进入到shell里面导入一下zpool
设置一下分区挂载点
1
| zfs set mountpoint=/ rock/os/gentoo
|
然后再重启一下就可以正常进入系统了。
定期备份
在Gentoo的Portage Tree中提供了一个sys-fs/zfs-auto-snapshot
的包,这个包可以帮我们创建一个定时任务周期性的备份我们的ZFS
1
| sudo emerge -av sys-fs/zfs-auto-snapshot
|
可以根据需要配置备份的周期:
1
2
| sudo zfs set com.sun:auto-snapshot:daily=true rock/os/gentoo
sudo zfs set com.sun:auto-snapshot:weekly=true rock/os/gentoo
|
后续工作
这次备份因为刚开始用ZFS很多地方不是很了解,然后用备份盘的时候吧系统导出去了(非加密的状态)。所以这里还是要再把这个备份盘格式化一下:
1
| sudo dd if=/dev/urandom of=/dev/sdc bs=1M status=progress && sync
|
结束语
这次搞得备份有点崩了,幸好是在开始备份之前在学姐的NAS上备份了一份不然真的就没了:-P
这次备份过程中也发现了可能存在的很有意思的玩法,比如说给虚拟机快速装一个和宿主机一样的系统,或者是创建基于当前的gentoo创建一个testing分支的dataset等等,这些玩法也会在后面的文章中记录。
参考资料