随着树莓派的不断使用,系统已不再是最初的系统。出于对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可以查看分区情况,如下图所示:

parted1.png

键入面的命令分区:

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

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

parted2.png

这时候可以看到两个分区已建立好,由于未进行格式化,所以“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卡、并格式化,加载格式化后的分区,按照数据拷贝流程进行数据迁移。

标签: ubuntu, 树莓派

已有 9 条评论

  1. li

    太棒了,谢谢你的分享,很好的解决了我的问题。超棒的教程!!

  2. 王宜中

    dump -0uaf - /mnt/usb2 | sudo restore -rf - 在做这一步操作时会报错 DUMP: You can't update the dumpdates file when dumping a subdirectory
    。把u给去掉就可以了。然后umount /mnt/image时提示设备正忙。能联系一下我吗?

    1. mxley

      umount提示设备正忙,应该和你cd /mnt/image有关,切换一个目录就可以了

  3. mxley

    按照文档做了img,dd到sd卡上在raspberry 3B+启动的时候,卡在random: crng init done。 查了一下,基本都说是img的问题,但又不明确具体啥问题。求破解

    1. 树莓

      最后有个非法指令的报警 illegal instructon

  4. new

    注意:为了避免出现“The resulting partition is not properly aligned for best performance.” 这样的错误,第一个分区的start起点为1。您好,这里给了提示,但没有给出解决方法

    1. new

      就生成了img,后面全部失败。

      1. 我跟你的遭遇一样,就生成了img ,然后用win32disk还原烧录新的sd卡直接启动不了

        我跟你的遭遇一样,就生成了img ,然后用win32disk还原烧录新的sd卡直接启动不了

  5. Effectively expressed indeed! .

添加新评论