随着树莓派的不断使用,系统已不再是最初的系统。出于对SD卡可靠性的担忧,我需要备份整个SD卡。同时手上另有一张空白的SD卡,如何复制SD卡并正常启动,是摆在我面前的难题。

一开始我使用dd来备份,但dd属于底层的设备块拷贝工具,大量的空白数据既占空间,备份速度又慢。更可恶的是,不同的SD卡真实大小不一样,同样是8G的SD卡,dd恢复回去后系统不能启动。只有从小镜像恢复到大SD卡才能成功。

经过漫长的有效数据备份探索,总算实现只备份有效数据。整个过程不需要任何付费软件,全部由Linux命令工具完成。

例中在一台独立的ubuntu系统中进行备份,通过插入树莓派的SD卡来读取数据。

生成空白镜像

使用下面的命令生成一个空白镜像文件,count为你需要的大小。sudo dd if=/dev/zero of=raspberrypi.img bs=1MB count=3000

> 注:也许你需要在树莓派上使用df -h命令,预先需要估计下img文件需要的大小。

镜像分区

parted可对img进行分区,如果没有这个命令,使用sudo apt-get install parted来安装。

首先需要给镜像添加Label,并标记为msdos格式。sudo parted raspberrypi.img mklabel msdos

这里仅标签,并未进行实际的格式化。标签后才能进一步分区。

然后键入下面的命令进入parted的交互分区界面。sudo parted raspberrypi.img

键入p可以查看分区情况,如下图所示:

linux备份系统镜像 linux系统做镜像备份_linux备份系统镜像

键入面的命令分区:mkpart primary fat32 1 32M

mkpart primary ext4 32M -1

> 注意:为了避免出现“The resulting partition is not properly aligned for best performance.” 这样的错误,第一个分区的start起点为1。

之后再次键入p查看分区情况,如下图所示:

linux备份系统镜像 linux系统做镜像备份_文件系统_02

这时候可以看到两个分区已建立好,由于未进行格式化,所以“File System”字段还是空的。

键入q推出parted界面。

格式化镜像中的分区

格式化工具不支持在img中格式化,所以需要先挂载镜像。

在 Linux 系统里,loop 设备是一种伪设备(pseudo-device),或者也可以说是仿真设备。它能使我们像块设备一样访问一个文件,如果这个文件包含有一个完整的文件系统,那么这个文件就可以像一个磁盘设备一样被 mount 起来。

连接loop设备sudo losetup --show -f raspberrypi.img

命令会返回链接后的设备路径,本例中为/dev/loop0。

连接设备后还需映射分区:sudo kpartx -va /dev/loop0

如果找不到kpartx,使用命令sudo apt-get install kpartx来安装。

kpartx运行成功将打印映射后的信息:add map loop0p1 (252:0): 0 61440 linear /dev/loop0 2048

add map loop0p2 (252:1): 0 5795840 linear /dev/loop0 63488

现在你可以在/dev/mapper目录下找到两个分区的符号。

总算可以格式化了,运行下面的命令:

sudo mkfs.vfat /dev/mapper/loop0p1
sudo mkfs.ext4 /dev/mapper/loop0p2
## 向分区中写入数据

首先需要把等待备份的SD卡用USB 读卡器连接到 Ubuntu,然后依次挂载SD卡的两个分区。sudo mkdir /mnt/usb1

sudo mkdir /mnt/usb2
sudo mount -t vfat /dev/sdb1 /mnt/usb1
sudo mount -t ext4 /dev/sdb2 /mnt/usb2

自行替换上述命令中的SD卡设备号。

创建一个用来挂载img镜像中分区的目录/mnt/image:sudo mkdir /mnt/image

挂载img中的fat分区sudo mount -t vfat /dev/mapper/loop0p1 /mnt/image

用cp命令拷贝SD卡的fat分区数据到镜像的fat分区:sudo cp -rfp /mnt/usb1/* /mnt/image

参数中:r递归拷贝,f强制读取,p不拷贝连接符号。

拷贝完成,卸载img的fat分区:sudo umount /mnt/image

再加载img的ext4分区:sudo mount -t ext4 /dev/mapper/loop0p2 /mnt/image

却换到mnt/image目录,ext4文件系统需要使用dump和restore来完整的导出有用数据:cd /mnt/image

sudo dump -0uaf - /mnt/usb2 | sudo restore -rf -

如果找不到dump,使用命令sudo apt-get install dump来安装。

dump的参数:0完全备份;

u当成功备份后信息写入/var/lib/dumpdates

a自动大小

f后跟-表明写到标准输入

/mnt/usb2指明从哪里dump数据

restore参数:r表明重建文件系统

目标系统必须为mke2fs类型

f后跟-表明从标准输入读取数据

清理

img制作完成,需要卸载镜像

sudo umount /mnt/image
sudo kpartx -d /dev/loop0
sudo losetup -d /dev/loop0
然后卸载掉SD卡:sudo umount /mnt/usb1
sudo umount /mnt/usb2

现在raspberrypi.img中已包含了完整的SD数据备份,可以使用dd恢复到任何大于3000M的SD卡中。

拓展

整个备份过程以制作img文件为目标,但其实可以直接进行SD卡与SD卡的复制。

用parted来分区目标SD卡、并格式化,加载格式化后的分区,按照数据拷贝流程进行数据迁移。