Raspberrypi 3 系统备份还原, 基于最小系统镜像实现

2023-05-16

Raspberrypi 3 备份还原系统

一、为什么要备份系统?

1 经常在树莓派上调试程序, 安装各种软件,越来越多的库和程序的安装带来的系统更改几乎是不可逆的,一旦某个程序或者驱动出现问题, 如果有备份, 可以快速方便的恢复到系统正常的状态
  
2批量发布树莓派产品,当在一台树莓派上把程序调试好后, 需要批量化到几十上百个树莓派, 如果每台树莓派再去安装一遍环境和程序, 需要耗费很多时间, 假如其中有用到apt-get安装的软件, 那更是不堪繁琐
二、备份系统镜像
    备份现有的系统镜像, 需要的时候既可以用来恢复系统, 又可以用来批量化生产, 非常方便。
目前的备份系统大多是基于SD卡的完整备份, 比如SD卡16G, 备份镜像也是16G,这带来了许多空间浪费,并且用镜像还原的时候, 新的SD卡容量必须要比镜像文件大,否则无法写入SD卡,况且就算同型号大小的SD卡, 容量不一定相等, 往往相差一点,这就导致镜像写入的时候经常出现SD卡容量就差那么一点点,结果无法使用。


    所以, 需要制作最小系统镜像, 按当前实际使用的空间来备份镜像, 而并非完整备份SD卡。


三、制作步骤

环境: Windows 7 64位 + 虚拟机Ubuntu 16 

树莓派 3 ,  Linux raspberrypi 4.9.35-v7+ #1014 SMP Fri Jun 30 14:47:43 BST 2017 armv7l GNU/Linux

1 如果直接在树莓派系统内部进行操作, 需要SD卡剩余空间大于已用空间, 一般来说大家使用的都是16G或者32G, 并没有多少剩余空间, 因此不采用此方案。因此我换到PC上的Ubuntu里面, 直接对已有的完整SD卡镜像进行处理。

2 在Wndows上先Win32 Disk Imager把树莓派的SD卡镜像完整读取出来放好, 我的镜像名称是rspi-backup-8G.img。

3 进入虚拟机Ubuntu16 , 你可以将SD卡完整镜像拷贝到虚拟机, 或者将路径共享到虚拟机, 我采用的后一种

4 安装虚拟机需要用到的工具

   sudo apt-get -y install rsync dosfstools parted kpartx

5 虚拟SD卡完整镜像为块设备

   sudo losetup -f --show 你的SD卡完整镜像路径

   

  完成后会显示路径为 /dev/loop0

6 挂载虚拟文件系统,即挂载上一步的/dev/loop0, 如下所示


挂载完成后会在/dev/mapper/ 路径下生成两个路径, 即/dev/mapper/loop0p1, /dev/mapper/loop0p2,

其中vfat格式的是boot分区, ext4的是root分区, 注意挂载后的路径在/medai/root/ (我用的root用户,所以在root路径下)

PS: ubuntu会自动挂载,如果你的系统没有自动挂载, 请手动挂载。



7 这步比较关键了, 根据上一步看到的分区大小, 可以发现root分区大小7G,实际使用4.3G, 有2.5G的空余空间

   我们要做的就是省下这部分空间。

   首先查看SD卡完整镜像大小,需要注意的是root分区是完整大小, root分区是使用的大小

    

    建立一个镜像文件,boot空间大小保持不变, root空间大小根据实际使用的大小增加一定冗余空间, 我取的30%冗余空间

种。    

    sudo dd if=/dev/zero of=rspi-backup.img bs=1K count=$totalsz

    (totalsz =  42030+4449932*1.3)

8 对虚拟镜像文件进行分区, 首先查看完整SD卡镜像的分区信息

  

可以获知, root分区从8192开始, 到93596结束,共85405块, root分区从94208开始,到15126527结束

我们新建的boot分区和这个保持一致, 需要缩减的是root分区, 因此我们分区如下

sudo parted rspi-backup.img --script -- mklabel msdos
sudo parted rspi-backup.img --script -- mkpart primary fat32 8192s 93596s
sudo parted rspi-backup.img --script -- mkpart primary ext4  94208s -1

-1(这里是数字1  不是字母L)

然后将此空镜像文件挂载进系统进行格式化

losetup -f --show rspi-backup.img
kpartx -va /dev/loop1
sudo mkfs.vfat /dev/mapper/loop1p1 -n boot
sudo mkfs.ext4 /dev/mapper/loop1p2

最后如下图所示

   

最下面的就是刚才挂载进来的空镜像,(图中我挂载的是已经制作好的镜像,所以已用空间不是0)

PS: Ubuntu在执行kpartx -va ***.img后会自动挂载里面的分区, 如果你在系统里面找不到, 请手动挂载。


10 现在SD卡完整镜像和空镜像都挂载进来了, 直接完整拷贝文件

sudo cp -rfpd $src_boot_path/* $dst_boot_path
sync
sudo cp -rfpd $src_root_path/* $dst_root_path
sync

其中 的src_boot_path等 为上图中的boot和root路径,自行查看


11 关键的一步, 每个生成的img文件的文件系统uuid不一样, 在完整拷贝的时候, 原来的镜像里面boot里面记录的UUID和root里面记录的UUID 是自己专有的, 拷贝到空img后, 和现有的不匹配, 如果不修改的话会导致系统boot完后无法jump到root分区, 导致无法进入系统。所以要修改UUID

如下所示查看UUID


替换我们的img内的PARTUUID

opartuuidb=`blkid -o export ${device}p1 | grep PARTUUID`
opartuuidr=`blkid -o export ${device}p2 | grep PARTUUID`
npartuuidb=`blkid -o export ${device_dst}p1 | grep PARTUUID`
npartuuidr=`blkid -o export ${device_dst}p2 | grep PARTUUID`
echo "BOOT uuid old=$opartuuidb -> new=$npartuuidb"
echo "ROOT uuid old=$opartuuidr -> new=$npartuuidr"
sudo sed -i "s/$opartuuidr/$npartuuidr/g" $dst_boot_path/cmdline.txt
sudo sed -i "s/$opartuuidb/$npartuuidb/g" $dst_root_path/etc/fstab
sudo sed -i "s/$opartuuidr/$npartuuidr/g" $dst_root_path/etc/fstab

最后的卸载清理工作

sudo umount /dev/mapper/loop0p1
sudo umount /dev/mapper/loop0p2
sudo umount /dev/mapper/loop1p0
sudo umount /dev/mapper/loop1p1
kpartx -d /dev/loop0
kpartx -d /dev/loop1    

得到如下镜像文件


拷贝到windows, 使用Win32 Disk Imager工具写入SD卡或者dd写入也行。 

树莓派开机进入系统, sudo raspi-config->Advanced options->Expand Filesystem, 确认重启, 

分区就扩大到你现在的SD卡大小了。


最后附上完整脚本,使用的时候在脚本后输入SD卡完整镜像的路径, 脚本运行完成后会在脚本运行路径生成一个名为rspi-backup.img的镜像文件

#!bin/bash
# backup img file to new img file,  delete the empty space
# e.g source a.img = 8G, 
# run this script
# the new b.img maybe = 5G or less
#
# created by liubo 20170825
#
if [ -z $1 ]; then
    echo "no argument, assume the *.img file path please !"
    exit 0
else
    imgpath=$1
fi

loopdevice=`losetup -f --show $imgpath`
echo "======1 losetup img file ========"
device=`kpartx -va $loopdevice | sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1`
device="/dev/mapper/${device}"
#echo $device $loopdevice
sleep 5
bootsz=`df -P | grep $device'p1' | awk '{print $2}'`
rootsz=`df -P | grep $device'p2' | awk '{print $3}'`
totalsz=`echo $bootsz $rootsz | awk '{print int(($1+$2)*1.3)}'`

echo "======2 make empty img file======"
echo 'boot :'$bootsz'K'
echo 'root :'$rootsz'K'
echo 'total:'$totalsz'K'

sudo dd if=/dev/zero of=rspi-backup.img bs=1K count=$totalsz


bootstart=`sudo fdisk -l $loopdevice | grep $loopdevice'p1' | awk '{print $2}'`
bootend=`sudo fdisk -l $loopdevice | grep $loopdevice'p1' | awk '{print $3}'`
rootstart=`sudo fdisk -l $loopdevice | grep $loopdevice'p2' | awk '{print $2}'`
echo "======3 format empty img========="
echo "boot: $bootstart >>> $bootend, root: $rootstart >>> end"
sudo parted rspi-backup.img --script -- mklabel msdos
sudo parted rspi-backup.img --script -- mkpart primary fat32 ${bootstart}s ${bootend}s
sudo parted rspi-backup.img --script -- mkpart primary ext4  ${rootstart}s -1

loopdevice_dst=`sudo losetup -f --show rspi-backup.img`
device_dst=`kpartx -va $loopdevice_dst | sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1`
sleep 1
device_dst="/dev/mapper/${device_dst}"
sleep 1
sudo mkfs.vfat ${device_dst}p1 -n boot
sleep 1
sudo mkfs.ext4 ${device_dst}p2
sleep 1

echo "======4 copy file to img========="
sleep 5
src_boot_path=`sudo df -lhT | grep $device'p1' | awk '{print $7}'`
src_root_path=`sudo df -lhT | grep $device'p2' | awk '{print $7}'`

dst_boot_path=`sudo df -lhT | grep $device_dst'p1' | awk '{print $7}'`
dst_root_path=`sudo df -lhT | grep $device_dst'p2' | awk '{print $7}'`

sudo cp -rfpd $src_boot_path/* $dst_boot_path
sync

#sudo rsync -aP $src_root_path/ $dst_root_path/
sudo cp -rfpd $src_root_path/* $dst_root_path
sync

# replace PARTUUID
echo "======5 replace PARTUUID========="
opartuuidb=`blkid -o export ${device}p1 | grep PARTUUID`
opartuuidr=`blkid -o export ${device}p2 | grep PARTUUID`
npartuuidb=`blkid -o export ${device_dst}p1 | grep PARTUUID`
npartuuidr=`blkid -o export ${device_dst}p2 | grep PARTUUID`
echo "BOOT uuid old=$opartuuidb -> new=$npartuuidb"
echo "ROOT uuid old=$opartuuidr -> new=$npartuuidr"
sudo sed -i "s/$opartuuidr/$npartuuidr/g" $dst_boot_path/cmdline.txt
sudo sed -i "s/$opartuuidb/$npartuuidb/g" $dst_root_path/etc/fstab
sudo sed -i "s/$opartuuidr/$npartuuidr/g" $dst_root_path/etc/fstab


echo "Create backup img done, clear job ? Y/N"
read key
if [ "$key" = "y" -o "$key" = "Y" ]; then
    sudo umount $src_boot_path
    sudo umount $src_root_path
    sudo umount $dst_boot_path
    sudo umount $dst_root_path
    kpartx  -d $loopdevice
    losetup -d $loopdevice
    kpartx  -d $loopdevice_dst
    losetup -d $loopdevice_dst    
fi
echo "==========Done==================="
exit 0




如有错误请指正。谢谢。

参考链接

http://blog.csdn.net/talkxin/article/details/50464313






本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Raspberrypi 3 系统备份还原, 基于最小系统镜像实现 的相关文章

  • 鸿蒙最新功能及承载设备详解:HarmonyOS 2及华为全场景新品发布会全纪录

    6月2日 xff0c 华为联手CSDN直播了 HarmonyOS 2及华为全场景新品发布会 xff0c 老猿全程观看直播 xff0c 并进行了回看 xff0c 力争将发布会的核心内容在本文中概要性地呈现 一 一生万物 万物归一 首先是华为消
  • 构建VisualStudio2019+OpenCV4.3的C++ windows编译环境

    一 引言 最近在读源代码研究CLAHE的算法 xff0c 但好久没学习C 43 43 了 xff0c 发现部分代码难以理解 xff0c 因此最后下决心装一个C 43 43 编译器 下载OpenCV源码 xff0c 这样碰到疑难问题就可以实际
  • 关于C++集合操作赋值和集合间操作的结果集合的疑问

    一 关于集合的疑问 最近对C 43 43 语言的集合操作比较感兴趣 xff0c 看了好友博主CP猫介绍的 C 43 43 中集合set的常用操作 xff0c 在使用时有3个疑问 xff1a 集合的变量赋值能否直接将一个集合实例赋值个另一个集
  • 如何使用Docker暴露多个端口?

    本文翻译自 xff1a How can I expose more than 1 port with Docker So I have 3 ports that should be exposed to the machine 39 s i
  • 人工智能基础概念1:模型、拟合、最大似然估计、似然函数、线性回归、sigmoid函数、逻辑回归

    一 模型 拟合 xff08 fitting xff09 和过拟合 xff08 overfitting xff09 人工智能中的模型 xff08 Artificial Intelligence Model xff09 指的是一些算法和数学模型
  • 中国移动提出的ABCDNETS和DSSN数联网技术介绍

    一 引言 在2023年4月14日 xff0c 中国移动召开 数据要素流通与治理产业高峰论坛上 xff0c 中国移动发布了 数联网 xff08 DSSN xff09 白皮书 xff0c 同时发布了全球首创的数联网 DSSN 服务平台等产品 x
  • Python循环语句(while循环、for循环)

    Python循环语句 一 while循环二 for语句三 range 函数四 break 和 continue 语句五 pass语句 Python循环语句主要有while循环和for循环 xff0c Python 循环语句的控制结构图如下所
  • 深度学习笔记一:深度学习环境的搭建

    首先需要下载anaconda xff08 官方网站下载 xff09 一路选择next即可 这里我没有选择添加环境变量 xff0c 如果有需要 xff0c 后期可以手动添加 xff0c 这里可以根据自己情况选择 安装完成后 xff0c 从wi
  • HAN论文模型代码复现与重构

    论文简介 本文主要介绍CMU在2016年发表在ACL的一篇论文 xff1a Hierarchical Attention Networks for Document Classification及其代码复现 该论文是用于文档级情感分类 xf
  • Http Digest认证协议

    http blog csdn net htjoy1202 article details 7067287 其认证的基本框架为挑战认证的结构 xff0c 如下图所示 xff1a xfeff xfeff 1 客户端希望取到服务器上的某个资源 x
  • 【系统分析师之路】嵌入式系统章节错题集锦

    系统分析师之路 嵌入式系统章节错题集锦 系分章节错题集第01题 xff1a 红色 01 雷达设计人员在设计数字信号处理单元时 xff0c 其处理器普遍采用DSP芯片 xff08 比如 xff1a TI公司的TMS320C63xx xff09
  • 【软工】程序编码

    目录 前言正文 程序设计语言 分类 选择原则 程序编码总原则 好程序的标准 结构化程序设计 主要内容 主要原则 程序设计风格 源程序文档化 数据说明 语句结构 输入输出方法 程序设计质量评价 正确性结构清晰性易修改性 易读性 简单性 程序复
  • TPM1.2到TPM 2.0的变化

    原文地址 xff1a http www vonwei com mod 61 pad amp act 61 view amp id 61 11 TPM 1 2规范主要面向PC平台 xff0c 其103版本在2009年被接受为ISO标准 xff
  • 关于Cmake与CmakeLists(一)--背景,须知,示例

    一 背景及须知 1 背景 xff1a VS2019与VS2010在编写程序时都是创建了一个工程 xff0c 然后直接打开 sln即可 但是vscode仅仅是一个编辑器 xff0c 打开之后只有 c或者 cpp文件 xff0c 故需要手动编译
  • webgl(three.js)实现室内定位,楼宇bim、实时定位三维可视化解决方案——第五课

    webgl three js 实现室内定位 楼宇bim 实时定位三维可视化解决方案 第五课 参考文章 xff1a xff08 1 xff09 webgl three js 实现室内定位 楼宇bim 实时定位三维可视化解决方案 第五课 xff
  • Linux虚拟机在线扩容lvm类型root分区

    目录 Linux虚拟机在线扩容lvm类型root分区写在前面正文写在后面 Linux虚拟机在线扩容lvm类型root分区 写在前面 这是我在CSDN上的第一篇文章 作为一个半江湖的IT人 xff0c 这些年来也在CSDN受益很多 今天是20
  • 无vCenter创建vSAN集群

    无vCenter创建vSAN集群 最近仍有朋友在问题 xff0c vCenter如果 挂了 xff0c vSAN还能正常运行吗 xff1f 这个小文通过手动创建vSAN集群的方式来解答下这个问题吧 xff08 生产环境慎用 xff01 xf
  • 记一次mdadm软raid1升级容量

    MDRaid 2块4TB做了软RAID1 xff0c 需要升级成2块8TB盘 查看磁盘信息 xff0c SerialNumber等会儿会用到 xff0c 防止换错盘 span class token function sudo span h
  • [简洁版]youtube-dl下载命令

    简介 YouTube dl是python上的pip模块 xff08 开源 xff09 xff0c 可以用来下载YouTube Bilibili等多个平台的视频 音频文件 xff0c 可谓是居家旅行必备小工具 本文主要介绍一些常用的youtu
  • [简版]VMware强大的管理工具-PowerCLI

    一 PowerCLI介绍 什么是 PowerCLI PowerCLI 是一个命令行工具 xff0c 可以用于自动化vSphere管理 xff0c 包括网络 存储 虚拟机以及其他很多功能 PowerCLI包含超过700个命令 要安装Power

随机推荐

  • [简版]使用PowerCLI自定义vSphere ISO安装镜像

    一 什么情况下要自定义ISO镜像 一般来说 xff0c 对于DELL Lenovo HPE这类主流的服务器厂商 xff0c VMware官方vSphere ISO镜像或者官网的第三方客制镜像 xff08 由服务器厂商提供的封装镜像 xff0
  • [简版] 关于vSphere漏洞-OpenSLP

    一 前言 近期vSphere OpenSLP漏洞在野利用的新闻频频被爆出来 xff0c 大伙儿非常关注 由于vSphere虚拟化客户之广泛 xff0c 很多朋友都表达了自己的焦虑 xff0c 同时也会担心自己管理的vSphere虚拟化平台是
  • [简版] Linux搭建SAMBA文件共享服务

    SMB服务搭建 更多参数含义参考链接 常用配置 安装samba span class token comment Ubuntu span span class token function sudo span span class toke
  • STM32 HAL库详解

    STM32 HAL库整体总结 STM32 之二 HAL库详解 及 手动移植 本篇博客是对以上参考资源的一个二次总结与整理 1 HAL库文件结构 对于开发人员而言 xff0c 首先要清楚 HAL 库的文件结构 根据文件类型可认为以下两大类 x
  • STM32 HAL库学习(四):DMA之串口空闲中断

    STM32CubeMX 配置实现参考这里 1 串口空闲中断 1 1 UART DMA方式接收数据 STM32串口使用DMA方式接收数据可以减小CPU的开销 对于接收定长数据 xff0c 可以将DMA接收缓冲区的长度设定为待接收数据的长度 x
  • Android Studio 启动模拟器出现“Timed out after 300seconds waiting for emulator to come online“解决方案

    Android Studio 启动模拟器出现 34 Timed out after 300seconds waiting for emulator to come online 34 解决方案 参考文章 xff1a xff08 1 xff0
  • 结构体中的位定义

    1 结构体位定义 在工作中 xff0c 经常遇到按位 xff08 bit xff09 定义结构体 的情况 由于一个字节有8个位 xff0c 这时 xff0c 程序员往往对bit的位置产生困惑 现在给出2个例子 xff0c 来说明位的定义次序
  • 蓝牙基础(三):蓝牙协议栈总体认知

    蓝牙基础 xff08 三 xff09 xff1a 蓝牙协议栈总体认知 0 前言 初入门经典蓝牙学习 xff0c 网上资料参差不齐 xff0c 本博客旨在整理自己的一些总结内容 xff0c 建立整体功能认识 xff0c 以便后续深入学习 1
  • FreeRTOS学习(四)任务调度与切换

    文章目录 1 任务调度2 任务切换2 1 SVC 和 PendSV2 2 上下文2 3 切换场景2 4 PendSV Handler 3 总结 1 任务调度 在建立完任务后紧接着调用任务调度函数 xff0c 便会使系统运行起来 span c
  • FreeRTOS学习(五)队列与信号量

    文章目录 1 队列1 1 队列特性1 2 队列创建1 2 1 接口函数1 2 2 内存占用1 2 3 创建过程分析 1 3 入队与出队1 3 1 队列项入队1 3 1 队列项出队 2 信号量2 1 二值信号量2 2 计数型信号量2 3 互斥
  • FreeRTOS学习(六)时间管理

    文章目录 1 延时函数1 1 vTaskDelay 1 2 vTaskDelayUntil 1 3 系统时钟节拍 2 软件定时器2 1 定时器概述2 2 定时器 API 3 总结 1 延时函数 当任务需要调用延时函数延时时 xff0c 任务
  • C语言 sscanf库函数

    目录 1 函数描述2 函数应用2 1 基础应用2 2 高级应用 1 函数描述 xff08 1 xff09 函数功能 xff1a 通常被用来解析并转换字符串 xff0c 从str指定的字符串读取数据 xff0c 并根据参数format字符串来
  • C语言 文件读写

    目录 1 文件打开与关闭1 1 打开文件 fopen 1 2 关闭文件 fclose 2 读取文件2 1 fgetc 2 2 fgets 2 3 fscanf 3 写入文件3 1 fputc 3 2 fputs 3 3 fprintf 1
  • C语言 条件编译

    目录 1 if elif else endif 2 ifdef else endif 3 ifndef else endif 4 三者区别 根据不同情况编译不同代码 产生不同目标文件的机制 xff0c 称为条件编译 条件编译是预处理程序的功
  • yolo 学习系列(三):训练参数与网络参数

    yolo 学习系列 xff08 三 xff09 xff1a 训练参数与网络参数 手把手教你做目标检测 xff08 YOLO SSD xff09 视频链接 1 训练参数 博主在使用 yolov2 tiny voc 训练 人 这一类目标物体时
  • Caffe 学习系列(七):MobileNet-YOLO 安装与训练

    Caffe 学习系列 xff08 七 xff09 xff1a MobileNet YOLO 安装与训练 基于darknet实现mobilenet 基于darknet框架实现DepthwiseConvolutional层 深度学习 xff08
  • 完美解决api-ms-win-crt-runtime-l1-1-0.dll 丢失问题

    完美解决api ms win crt runtime l1 1 0 dll 丢失问题 参考文章 xff1a xff08 1 xff09 完美解决api ms win crt runtime l1 1 0 dll 丢失问题 xff08 2 x
  • Moveit!入门——古月居机械臂开发笔记(一)

    Moveit 入门 古月居机械臂开发笔记 xff08 一 xff09 引言Moveit xff01 与机械臂控制1 创作机械臂模型2 生成配置文件3 如何使用Moveit xff01 实现机械臂仿真 xff08 gazebo xff09 完
  • 数据处理:Excel读取txt文本

    数据处理 xff08 一 xff09 xff1a Excel读取txt文本 1 1 任务需求 txt 文本为四列数据 xff0c 以空格为分隔符号 xff0c 现导入 Excel 中 1 2 实现步骤 新建 excel 文件点击 数据 来自
  • Raspberrypi 3 系统备份还原, 基于最小系统镜像实现

    Raspberrypi 3 备份还原系统 一 为什么要备份系统 xff1f 1 经常在树莓派上调试程序 xff0c 安装各种软件 xff0c 越来越多的库和程序的安装带来的系统更改几乎是不可逆的 xff0c 一旦某个程序或者驱动出现问题 x