视频加载失败

【树莓派】SD卡系统备份

1137 字
6 分钟
【树莓派】SD卡系统备份
【树莓派】SD卡系统备份

0x00 前言#

一般常见简单的备份方式是是使用Win32DiskImager备份,但是有几个缺点:

  1. 整卡备份,Win32DiskImager会将SD卡内的所有区块都会备份下来,就类似Linux的dd命令。一个SD卡是16G但里面的数据只有100M,那么备份下来的文件就是16G,生成的备份文件大小就是SD的大小,这无疑浪费了空间
  2. 备份时间长,前面提到Win32DiskImager会将SD卡的所有块都备份下来,因此备份时间也就长了。
  3. 恢复时卡的容量必须要和备份文件大小一致或更大,这样就会造成一个问题,原本一张16G的卡内只有100M的有效数据,现在如果想将数据恢复到一张8G的卡,那么通过这种备份的方式是行不通的。

最后通过查找找到了一个更好方法,就是通过dump备份,恢复时也只恢复有效数据,因此只要恢复的SD卡比有效数据大就行了。

0x01 需要的软件#

  • dump 备份工具,用于备份系统

  • dosfstools fat32格式化工具,引导文件分区是fat32格式的

  • parted 分区调整工具

  • kpartx 虚拟文件系统工具

安装:

Terminal window
apt install dump -y &&
apt install dosfstools -y &&
apt install parted -y &&
apt install kpartx -y

0x02 创建img文件#

img是用于存储系统的镜像文件

首先使用df -h查看实际空间大小,再生成文件,比如:

Filesystem Size Used Avail Use% Mounted on
/dev/root 15G 8.9G 5.0G 65% /
/dev/mmcblk0p1 252M 72M 180M 29% /boot

从上可以看出实际使用空间8.9G+252M的boot空间

需要注意这里显示的空间单位是G,这里的G是将大小舍入到接近GiB(2302^{30}字节),而不是GB(10910^{9}字节)。

GB和GiB是两个有严格区别的单位,GB是方便10进制计算,GiB是方便2进制计算。

(插个题外话,Windows中默认的大小单位显示的是KB、MB、GB实际上计算的是KiB、MiB、GiB)

因此需要生成的img需要大于等于8.9G+252M

Terminal window
dd if=/dev/zero of=raspi.img bs=1M count=9570

if是输入路径,这里选择使用0填充

of是输出路径,就是创建img文件的路径

bs是块大小,这里选择M,也就是MiB,这样生成的文件是512bytes的整数倍,为了与分区表对上

count是块数,bs*count=真实大小

因为要生成的img文件需要大于等于8.9G``+252M,而这里的8.9G是进行了大小舍入所以不精确,所以为了容纳误差而选择生成9.1G`大小的系统。

因为bs是M,所以count为:(9.1×230÷220)+252≈9570(9.1\times2^{30}\div2^{20})+252\approx9570

0x03 img镜像分区#

分区前通过fdisk -l查看树莓派分区

Device Boot Start End Sectors Size Id Type
/dev/mmcblk0p1 * 8192 524287 516096 252M c W95 FAT32 (LBA)
/dev/mmcblk0p2 524288 31223807 30699520 14.7G 83 Linux

可以看到SD卡有两个分区,其中关键信息为:

  1. /dev/mmcblk0p1是引导分区(boot),分区类型是fat32,从8192柱面开始,到524287柱面结束。
  2. /dev/mmcblk0p2是系统分区,分区从524288柱面开始。

接下来使用parted将刚生成的img文件进行分区

Terminal window
parted raspi.img -s -- mklabel msdos # 创建msdos分区表
parted raspi.img -s -- mkpart primary fat32 8192s 524287s # fat32分区从8192开始,到524287结束
parted raspi.img -s -- mkpart primary ext4 524288s -1 # 系统分区一般都是ext4类型,从524288开始,到最后

0x04 挂载img并格式化#

将img挂载为虚拟设备,并获取虚拟设备地址

Terminal window
loopdevice=`losetup -f --show raspi.img`

使用kpartx挂载为虚拟文件系统

Terminal window
device=`kpartx -va $loopdevice | sed '1!d' | sed -E 's/.*(loop[0-9])p.*/\1/g'`

地址拼接

Terminal window
device="/dev/mapper/${device}"
imgBoot="${device}p1"
imgRoot="${device}p2"

格式化

Terminal window
mkfs.vfat $imgBoot
mkfs.ext4 $imgRoot

0x05 备份#

创建两个临时挂载目录,并挂载

Terminal window
mkdir tmpBoot tmpRoot
mount -t vfat $imgBoot tmpBoot
mount -t ext4 $imgRoot tmpRoot

备份Boot

Terminal window
cp -rfp /boot/* tmpBoot

备份系统

Terminal window
cd tmpRoot
dump -0uaf - / | restore -rf -
cd -

0x06 修改启动文件#

因为树莓派启动需要对应分区的PARTUUID,所以需要修改cmdline.txt和fstab文件

首先使用blkid命令查看分区PARTUUID

Terminal window
blkid -o export $imgBoot
blkid -o export $imgRoot

分别输出

DEVNAME=/dev/mapper/loop0p1
SEC_TYPE=msdos
UUID=161A-ED14
TYPE=vfat
PARTUUID=e74ab5ad-01
DEVNAME=/dev/mapper/loop0p2
UUID=20aa2e77-a211-4d43-996d-324f015e597c
TYPE=ext4
PARTUUID=e74ab5ad-02

可以看到PARTUUID分别为e74ab5ad-01(对应boot分区)和e74ab5ad-02(对应系统分区)。

将获取到的PARTUUID分别替换掉cmdline.txt和fstab文件中的PARTUUID

路径:

tmpBoot/cmdline.txt # cmdline.txt
tmpRoot/etc/fstab # fstab

0x07 END#

卸载分区

Terminal window
cd ~
umount tmpBoot/ tmpRoot/
rm -rf tmpBoot/ tmpRoot/

卸载虚拟设备

Terminal window
kpartx -d $loopdevice
losetup -d $loopdevice

至此系统备份就做好了,制作的img文件可以使用Win32DiskImager或dd刷入其他的SD卡了

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!

打赏
【树莓派】SD卡系统备份
https://rehtt.com/posts/251/
作者
Rehtt
发布于
2022-01-09
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
Rehtt
Hello, I'm Rehtt.
公告
欢迎来到我的博客!
分类
标签
最新动态
站点统计
文章
150
分类
17
标签
73
总字数
67,772
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.16.8
文章许可
CC BY-NC-SA 4.0
文章目录