如何克隆树莓派系统到较小的硬盘/SD卡上(如何分区、设置修复引导)

最近有个老固态硬盘空下来了,虽然写入速度没那么快,但是足够满足千兆网络了,所以我就想把现在给树莓派使用的固态硬盘换下来。由于一些设置很浪费时间,所以我不打算重装系统。此外这个老固态是 120GB 的,要小于正在使用的固态硬盘(512GB),所以一些常见的复制硬盘的方法就不能使用了。

本文只需要使用树莓派,但是我是使用 SSH 访问树莓派的,所以截图会是 macOS 的样式。

在写完文章后,我自己又照着重新弄了一遍,确定没啥问题,但还是建议读者先对重要文件进行备份,以防万一。

为什么不使用dd或SD card copier

本文不会使用 CLI 程序dd或 GUI 应用程序 SD card copier。

不使用dd因为这些程序复制的时候,是把整个盘复制了,这就导致写入肯定会失败(目标盘小于目的盘)。而且速度很慢,就算尽量减少传输经过的控制器数量和提高传输接口,但是从固态写固态也就是 30~45MB/s(不优化的话就 15~20MB/s)。

但是SD card copier 没有这个问题。不使用 SD card copier 是因为我还要插 HDMI 的线,而且不适合平时备份等操作,所以想研究一下使用 CLI 的方式。如果你能使用桌面模式,那么推荐直接使用 SD card copier 应用程序。而且这种方法要快很多,速度能稳定在 50~70MB/s。

原理

本文的方法和 SD card copier 原理是一样的:先在目标硬盘上分两个区,启动区(名称为bootfs,格式为 Windows_FAT_32)和使用区(也被称为根区名称为rootfs,格式为 Linux),然后使用rsync复制,这样速度也快很多。

如果在树莓派上使用lsblk -f(这里只是为了演示,后面会介绍一个信息更详细的工具)查看硬盘的结构和文件系统可以看到:

请添加图片描述

如果你好奇树莓派的启动分区bootfs为啥不使用 ext4 文件系统,这是因为要求最小为 16 GiB,但是启动区占这么大有点离谱了。此外,使用 FAT32 这种在 Windows、Linux、macOS 上都可以读取的文件系统,也方便更改一些设置(树莓派可以通过修改启动区bootfs中的文件来修改一些配置的,比如 HDMI 级别等)。

由于启动需要,我们需要分区是按照“启动区-使用区”的顺序存在于硬盘上。所以我们需要先格式化出启动区,再将剩余部分格式化为使用区。

第一步:分区和新建文件系统

首先将两个盘连到树莓派上,记得将目标硬盘格式化成 Linux 可以识别的文件系统(Mac 上可以使用磁盘工具格式化为 exFAT,或者使用 Raspberry Pi Imager 将其格式化成 FAT32)。

接下来使用parted工具进行分区,倒不是因为可以进行交互操作,主要是可以显示更详细的分区信息,而且设置一些参数也更方便。

首先使用sudo parted -l命令当前连接的硬盘信息:

请添加图片描述

第一部分是系统盘,我们可以看到其中的每个分区的大小、起始地址、终止地址、文件系统等等信息。第二部分是我们的目标硬盘。

然后我们使用下面的命令在目标硬盘生成相似分区结构:

sudo parted /dev/sdb --script 'mklabel msdos mkpart primary fat32 4194.5kB 541MB mkpart primary ext4 541MB 120GB print quit'
  • /dev/sdb是目标盘的设备名称。不要使用/dev/sdb1,这是已存在的分区名称。
  • 使用--script则不会进入交互模式,这样一条命令即可完成操作。需要注意官方没有使用这个选项,但是如果按照上面的内容,不使用该选项,直接尾接后面的命令,那么会摧毁整个硬盘的分区(会有提示)。
  • mklabel msdos设置分区模式为 MBR 格式。这里不使用gpt是因为系统上就是msdos(从上图的Partition Table可以看到这个信息)。
  • mkpart primary fat32 4194.5kB 541MB 这部分是划分启动区的命令,primary表示是独立分区(或者称为“主分区”,对应的是“扩展分区”)。使用fat32文件系统,起始地址使用4194.5kB,因为树莓派启动是从第 8192 块开始的,但是parted显示的数值是有误差的,以sudo fdisk -l的显示内容为准。终止地址和系统盘的终止地址一样就行。
  • mkpart primary ext4 541MB 120GB这部分是划分根区的命令,使用ext4文件系统,起始地址就是启动区的终止地址,但是终止地址是硬盘的大小,也就是和最开始图中显示的终止地址一样。
  • print会打印出分区信息。
  • exit会退出parted

需要注意个命令不能拆成两个,因为退出后再使用mkpart会抹除原有分区,这样最后还是生成一个分区。

显示如下:

请添加图片描述

这时工作还未全部完成,我们需要手动给两个分区手动创建一下FAT32ext4文件系统,如下:

sudo mkfs.vfat -F 32 /dev/sdb1
sudo mkfs.ext4 -L rootfs /dev/sdb2

如果不进行这一步,那么会出现一些很奇怪的问题。前面分区的信息中,正确显示了我们是创建了一个供ext4使用的分区,编号为2。但是如果你用sudo parted -l查看一下,会发现如下情况,File system一栏中,第二个分区没有任何信息:

请添加图片描述

这时候加载这个分区发现会提醒以下错误信息:

$ sudo mount /dev/sdb2 /mnt/rootfs/
mount: /mnt/rootfs: wrong fs type, bad option, bad superblock on /dev/sdb2, missing codepage or helper program, or other error.dmesg(1) may have more information after failed mount system call.
mount: (hint) your fstab has been modified, but systemd still usesthe old version; use 'systemctl daemon-reload' to reload.

所以手动创建。

第二部:使用rsync进行复制

在使用rsync进行复制之前,需要将两个分区加载一下。

首先是在/mnt/目录下新建一个目录,用来装载根分区:

sudo mkdir /mnt/rootfs 

然后装载根分区:

sudo mount /dev/sdb2 /mnt/rootfs/

那么从哪复制(同步)到哪呢?还记得文章第一张图中的内容吗?显示了系统盘上两个分区对应的目录:/boot/firmware(启动分区)和/(根分区)。

首先是启动分区:

sudo rsync -axHAWXS --numeric-ids --info=progress2 --exclude={"/mnt/","/boot/firmware/"} /* /mnt/rootfs

这里的选项意思如下:

  • a是存档模式,这会递归读取目录,不破坏符号链接、权限等信息。
  • x表示不会跨越文件系统的边界。
  • H保留硬连接。
  • A保留ACL(访问控制表)。
  • W禁用网络传输使用的增量算法。由于这里是都是本地路径,所以可以提高速度。
  • S 可以有效地处理稀疏文件,这样传输完占用的空间更少。(不用这个的话,所有源文件可能 8GB,但是目的文件总和可能有 10GB)
  • numeric-ids使用数字 ID,而不是映射。
  • info=progress2会显示传输进度和信息,而且是整个传输的进度和信息,而不是每个文件的统计信息。
  • 有几个目录不需要复制,因为是重复的,所以要使用--exclude=来排除它们。在很多关于系统克隆的文章中,列出了其他可以忽略的目录/dev/sys/proc,但是在我花了两个小时抢救之后,可以确定像/dev/sys/proc这些都是不能忽略的,(关于如何抢救如果写了一篇博客我会在这里列出链接)

这里解释一下排除的两个目录。

  • 第一个/mnt/是避免重复复制,因为这里就是复制的目的地。不然会复制两次甚至更多次。
  • 最后一个/boot/firmware/是因为这部分内容是启动的内容,我们后面单独复制(一起复制可能会跳过这部分)。

在复制/sys/目录下的部分文件会提示一堆错误。这些错误不用管,因为不能读取(显示没权限)或者是虚拟文件。详细内容可以看看这个帖子:Why does rsync fail to copy files from /sys in Linux? - Unix & Linux stackexchange

由于前面排除了一些目录,所以这里需要手动创建它们:

sudo mkdir /mnt/rootfs/mnt /mnt/rootfs/boot/firmware

然后就可以装载启动分区了:

sudo mount /dev/sdb1 /mnt/rootfs/boot/firmware/

然后就是复制启动分区,这里大部分选项和启动分区中的选项一样:

sudo rsync -axHAWXS --numeric-ids --info=progress2 /boot/firmware/* /mnt/rootfs/boot/firmware/

如果你比较细心的话,会发现原先红色的软链接文件现在变蓝了:

请添加图片描述

可以靠这个现象判断是否复制成功。但是并不是所有的文件都能这样判断的,比如说/proc/中的一些软链接文件可能需要后续自动更新和生成才能变红。

第三步:修复/etc/fstab/boot/cmdline.txt

/etc/fstab文件会列出启动时自动挂载的所有磁盘分区。由于我们是直接复制的,UUID 对不上,所以需要手动进行修改。

使用sudo fdisk -l可以在Disk identifier部分看到硬盘的标识符,这个我们后面需要用:

请添加图片描述

可以看到/dev/sdb1/dev/sdb2两个分区的 UUID。根据这个内容对相应的文件进行修改,需要注意修改的文件是/mnt/rootfs/etc/fstab(路径可能会有所不同),而不是系统盘中的/etc/fstab

/mnt/rootfs/etc/fstab的两个PARTUUID=的后面修改成对应的内容即可,如下(下图是没改完的,按理说两个 UUID 只有后面编号不同):

请添加图片描述

然后修改/mnt/rootfs/boot/cmdline.txt(这是个软链接,实际文件在firmware中)中的相应部分(下图中高亮部分):

请添加图片描述

这时候就一切完工了。我们可以关机、拔掉原来的硬盘启动试试看(一定要拔掉旧的,不然可能会用旧的启动分区来启动新的,我在实验的时候遇到过,然后又抢救了一回硬盘)。

可以看到能直接使用,几乎没什么区别,使用sudo fdisk -l查看硬盘可以看到现在的/dev/sda是这个硬盘了。

请添加图片描述

希望能帮到有需要的人~

参考资料或扩展阅读

本文虽然我付出了不少的时间和精力进行实验和尝试,但是也要感谢很多人编写的博客为我提供了思路和解决方案。

How can I change the volume name of a FAT32 filesystem? - Unix & Linux stackexchange:这篇帖子介绍了如何给 FAT32 修改分区名。

How to Format Disk Partitions in Linux - Dejan Tucakov:从这篇文章中我才知道某些命令行分区工具并不会创建文件系统,然后我发现parted也是。

Clone File System Hierarchy to Another Disk With Rsync - Francesco Galgani:这篇文章介绍了如何使用rsync克隆磁盘,也为我解决了很多rsync复制的问题,还为我调整启动引导提供了灵感。文章主要是关于大众设备上的 Linux 系统,所以只提及了/etc/fstab,而且引导是通过 GRUB。树莓派自己的系统的引导是通过config.txtcmdline.txt文件进行的。如果你想尝试 GRUB 引导启动树莓派,那么可以看看这个贴子GRUB on RPi 4 - Raspberry Pi Forums(我没有尝试,对内容实际意义不做保证)。

The config.txt file - Raspberry Pi Documentation:这是config.txt的官方文档,虽然本文没使用到config.txt,但是在这篇文档中介绍了树莓派的大致启动流程,我也是从中发现cmdline.txt,才能完成最后的修复工作。

Raspberry Pi 4 and Raspberry Pi 5 Boot Flow - Raspberry Pi Documentation:这部分文档介绍了详细的启动流程,作为扩展阅读可以看看。

Raspberry Pi 4/400 Bootloader Firmware Update/Recovery Guide - James A. Chambers:这篇博客介绍了如何修复和更新树莓派 4/400 的启动器固件。因为两个硬盘有时候不小心同时连接到树莓派启动,可能会导致启动器固件出现问题。可以看看这篇文章修复固件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/713620.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

redis实现分布式全局唯一id

目录 一、前言二、如何通过Redis设计一个分布式全局唯一ID生成工具2.1 使用 Redis 计数器实现2.2 使用 Redis Hash结构实现 三、通过代码实现分布式全局唯一ID工具3.1 导入依赖配置3.2 配置yml文件3.3 序列化配置3.4 编写获取工具3.5 测试获取工具 四、运行结果 一、前言 在很…

leetcode 热题 100_最长连续序列

题解一: 哈希表:找连续最长的数字序列,很容易联想到排序,但排序的时间复杂度O(nlogN)过大,判题容易超时。因此我们需要使用哈希表来快速查找,序列中是否存在与某个数相邻的数。用HashSet建立哈希表并去重&a…

【Javascript编程实操02】1、判断一个年份是闰年还是平年 2、找到三个数中最小的数

目录 前言 1、判断一个年份是闰年还是平年 原理: 代码: 实现效果: 2、找到三个数中最小的数 流程图: 代码: 实现效果: 总结 前言 本次继续针对Javascript阶段的if...else...的实操练习&#xff0…

IDEA 配置股票插件

IDEA配置股票基金实时查看插件,步骤如下: 打开Settings,找到Plugins,在Marketplace中搜索:Money Never Sleeps,如下图所示: Money Never Sleeps是IntelliJ IDEA平台插件. 支持查看股票实时行情…

three.js 叉乘判断物体在人前左,前右,后左、后右

效果&#xff1a; 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs"></div><div style"padding: 10px;text-align: left;">叉乘判断物体…

加密与安全_探索对称加密算法

文章目录 概述常用的对称加密算法AESECB模式CBC模式 (推荐)ECB VS CBC 附&#xff1a;AES工具类总结 概述 对称加密算法是一种加密技术&#xff0c;使用相同的密钥来进行加密和解密数据。在这种算法中&#xff0c;发送方使用密钥将明文&#xff08;未加密的数据&#xff09;转…

14:00面试,14:07就出来了,问的问题过于变态了。。。

我从一家小公司转投到另一家公司&#xff0c;期待着新的工作环境和机会。然而&#xff0c;新公司的加班文化让我有些始料未及。虽然薪资相对较高&#xff0c;但长时间的工作和缺乏休息使我身心俱疲。 就在我逐渐适应这种高强度的工作节奏时&#xff0c;公司突然宣布了一则令人…

kafka学习笔记三

目录 第二篇 外部系统集成 第三篇 生产调优手册 第1章 kafka硬件配置选择 第2章 生产者调优 2.1 生产者核心参数配置 2.2 生产者如何提高吞吐量 2.3 数据可靠性 2.4 数据去重 2.5 数据有序 2.6 数据乱序 第3章 Kafka Broker调优 3.1 Broker核心参数配置 3.2 其他 …

禅道:提bug、管理case 7.0

一、禅道的介绍 &#xff08;1&#xff09;定义禅道是一个项目管理工具&#xff0c;也是一个bug管理工具&#xff0c;还是一个用例管理工具。 &#xff08;2&#xff09;作用&#xff1a;为了解决众多企业在管理中出现混乱&#xff0c;无序的现象&#xff0c;开发出来 &…

ppt中调整某条表格框线的格式

1、先设置好边框线的属性&#xff1a; 2、选择要调整的边框线所在的单元格&#xff08;第二列的右边框加粗&#xff0c;体现分栏的效果&#xff09; 3、设计--边框--中选择要调整的边框线位置&#xff08;假设要调整右框线&#xff09;

libvirt命名空间xmlns:qemu的使用

示例xml <domain type{domain_type} xmlns:qemuhttp://libvirt.org/schemas/domain/qemu/1.0><qemu:commandline><qemu:commandline><qemu:arg value-newarg/><qemu:env nameQEMU_ENV valueVAL/></qemu:commandline></domain>"…

13、输入捕获实验

目录 一、通用定时器输入捕获概述 二、常用寄存器和库函数配置 三、输入捕获实验讲解 一、通用定时器输入捕获概述 STM32输入捕获工作过程&#xff08;通道1为例&#xff09; 一句话总结工作过程&#xff1a; 通过检测TIMx_CHx上的边沿信号&#xff0c;在边沿信号发生跳变…

28.HarmonyOS App(JAVA)多页签的实现(Tab)

HarmonyOS App(JAVA)多页签的实现&#xff08;Tab&#xff09; 页面可左右滑动&#xff0c;点击界面1,2,3切换到对应界面 PageSlider的创建和使用 在layout目录下的xml文件中创建PageSlider。 <PageSlider ohos:id"$id:page_slider" ohos:height"300vp&…

2D割草/吸血鬼游戏 性能优化——GPU Spine动画

视频中万人同屏方案(gpu动画、渲染、索敌、避障等功能)&#xff0c;可某宝搜店铺&#xff1a;【游戏开发资源商店】获取整套方案源码。 在过去的几年里&#xff0c;割草、类吸血鬼玩法的游戏频出爆款&#xff0c;其丰富的技能、满屏特效、刷怪清屏的解压畅快是此类游戏的核心&…

【MySQL】复合查询(重点)-- 详解

一、基本查询练习回顾 1、查询工资高于 500 或岗位为 MANAGER 的雇员&#xff0c;同时还要满足他们的姓名首字母为大写的 J 2、按照部门号升序而雇员的工资降序排序 3、使用年薪进行降序排序 4、显示工资最高的员工的名字和工作岗位 5、显示工资高于平均工资的员工信息 6、显…

韦东山嵌入式Liunx入门驱动开发四

文章目录 一、异常与中断的概念及处理流程1-1 中断的引入1-2 栈(1) CPU实现a ab的过程(2) 进程与线程 1-3 Linux系统对中断处理的演进1-4 Linux 中断系统中的重要数据结构(1) irq_desc 结构体(2) irqaction 结构体(3) irq_data 结构体(4) irq_domain 结构体(5) irq_domain 结构…

Redis入门与应用

Redis入门与应用 Redis的技术全景 Redis一个开源的基于键值对&#xff08;Key-Value&#xff09;NoSQL数据库。使用ANSI C语言编写、支持网络、基于内存但支持持久化。性能优秀&#xff0c;并提供多种语言的API。 两大维度 两大维度&#xff1a;应用维度、底层原理维度 我们…

记一次dockerfile无法构建问题追溯

我有一个dockerfile如下&#xff1a; ENTRYPOINT ["/sbin/tini"&#xff0c;"-g", "--"] CMD /home/scrapy/start.sh 我原本的用意是先启动tini&#xff0c;再执行下面的cmd命令启动start.sh。 为啥要用tini&#xff1f; 因为我的这个docker…

git介绍4.2

git(版本控制工具) 一、git 介绍 1、git是目前世界上最先进的分布式版本控制系统&#xff0c;可以有效&#xff0c;高速的处理从小到大的项目版本管理。 2、git是linux torvalds 为了帮助管理linux内核开发二开发的一个开放源码的版本控制软件。 3、git作用&#xff1a;更好…

PageHelper开源框架解读

在使用springboot开发系统时&#xff0c;列表查询经常会用PageHelper来进行分页。使用起来很方便&#xff0c;但从未想过它的实现原理&#xff0c;所以对其进行解读。 Service public class ScUserServiceImpl extends ServiceImpl<ScUserMapper, ScUser> implements IS…