文章目录
初次使用树莓派3/4安装系统时,需要先在官网下载img系统文件,再使用Win32DiskImager工具写入早tf卡中。之后在根据我们的产品进行各种配置、搭建环境等。
当产品小批量量产时,可以直接树莓派系统下使用dd
命令将当前系统完整地拷贝外接的ft卡中。完整系统拷贝,实际就是将整个tf卡的分区数据全部拷贝一次,32G的tf卡,就需要拷贝32G数据,不论实际使用空间为多少。
但是当产品大批量量产时,这种操作的效率就极其低下,系统tf卡容量更大时表现更明显,并且外接的tf卡容量不能小于当前tf卡容量。
这里,我们先借助DiskGenius的克隆分区功能,介绍两种高效的方式。为求方便,还介绍了在linux下使用pishrink脚本进行精简一次性制作,这也是强烈建议的操作方式。
另外,博文【挂载并修改img镜像的分区文件】还介绍对于已经制作好了img镜像文件,如果需要替换系统镜像中的一些文件或者修改内容,而不用重新制作一份系统。
1、DiskGenius版本
从v5.3开始,DiskGenius增加了克隆分区。因此需要选择v5.3及以上版本。由于在windows下,linux下的文件系统下某些字符不能识别,导致复制时提示文件不存在的情况,如下文件
/usr/share/ca-certificates/mozilla/NetLock_Arany_=Class_Gold=_Főtanúsítvány.crt
若出现问题,更换其他版本尝试。当前测试使用 v5.4.2.1239 x64 中文版本。
克隆分区时的三个选项:
- 复制所有扇区:复制所有扇区,类似linux下的dd命令,速度慢,要求两个分区大小一致
- 按文件系统原样复制:要求分区大小一致,仅复制有效扇区,速度最快。
- 按文件复制:要求目标分区容量大于当前文件数据总量,仅复制文件(分区参数?)
第二种方式,可以直接对一个ft写入,保持分区结构一致,插入树莓派卡槽可以直接启动。相对第一种已经快了很多。
我们介绍使用第三种,直接一个最小的img文件,分发后使用Win32DiskImager写入,或者其他批量写入工具。
2、制作最小的img镜像
目的是最小的img镜像(产品使用的基本软件、环境都已经安装好),仅复制文件和有效数据,也就是第三种方式。
2.1、查看现有树莓派系统tf卡的信息
使用diskgenius查看,具有两个分区boot和rootfs,关注文件系统、标识、柱面、磁头、扇区等信息。
boot分区详细信息如下,启动分区,大小为256M
rootfs分区详细信息,linux下的文件系统,使用大小为1.9G
2.2、创建img文件
菜单栏中,依次选择"硬盘"=>“新建虚拟磁盘文件”=>“新建.img文件”。
通过前面两个分区,root分区大小为256M,固定的;rootfs实际使用了1.9G。总的容量,我们设置稍微大一些,避免分区时占用一些空间,保证剩余控件大于1.9G,如2.5G,因此设置如下图,
等待结束,将增加了一个虚拟的磁盘。接着删除掉Img(0)分区。
2.3、创建分区
(1)创建一个root分区
保证大小一致,分区参数一致(参看上一节的截图信息)。
点解确定,将出现一个为格式化(0)的分区,分区参数和前面的一致。
点击保存修改,之后再修改盘符为boot。
(2)创建rootfs分区
接着,将剩余空闲的2.2G空间建立一个分区即可,不需要设置具体参数,注意设置Ext4文件系统。
确定后,保存,修改盘符为rootfs
2.3、复制分区文件
原有的系统tf卡显示名称为 RD2:MassStorageDevice(15GB),img镜像文件的显示名称为 VD0:raspberry.img(3GB)。分别使用克隆分区功能,将RD2的两个分区数据复制到VD0的对应分区中。
右键 RD2的boot分区,点击克隆分区,选择目标分区VD0的boot,选择任意一个选项即可,开始复制等待结束。
右键 RD2的rootfs分区,点击克隆分区,选择目标分区VD0的rootfs,选择按文件复制,开始等待结束。
2.4、最小img镜像测试
类似官方img文件烧写系统到tf中,使用Win32ImageManager将我们制作的raspberry.img文件写入到新的tf卡,之后树莓派卡槽中上电启动。linux下的脚本为sudo dd if=raspberry.img of=/dev/sdX bs=4M conv=fsync
,其中/dev/sdx是插入的tf卡设备。
开机后,查看空间如下,tf卡实际空间有29.7G,但是rootfs分区分配了2.3G。
pi@raspberrypi:~ $ sudo lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
mmcblk0 179:0 0 29.7G 0 disk
├─mmcblk0p1 179:1 0 256M 0 part /boot
└─mmcblk0p2 179:2 0 2.3G 0 part /
pi@raspberrypi:~ $ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 2.2G 1.6G 460M 79% /
devtmpfs 1.8G 0 1.8G 0% /dev
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 1.9G 8.4M 1.9G 1% /run
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/mmcblk0p1 253M 48M 205M 19% /boot
tmpfs 378M 0 378M 0% /run/user/1000
需要 sudo raspi-config 扩展 SD 卡使用空间,依次执行 sudo raspi-config => 6 Advanced Options => A1 Expand Filesystem,确认之后重启,再次查看
pi@raspberrypi:~ $ sudo lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
mmcblk0 179:0 0 29.7G 0 disk
├─mmcblk0p1 179:1 0 256M 0 part /boot
└─mmcblk0p2 179:2 0 29.5G 0 part /
2.5、可能遇到的问题
卡在boot界面,或者能进入但是没有文件系统等,大概率是因为加载分区有问题。关注partuuid,命令为
pi@raspberrypi:~ $ sudo blkid
/dev/mmcblk0p1: LABEL_FATBOOT="boot" LABEL="boot" UUID="5DE4-665C" TYPE="vfat" PARTUUID="15a061d1-01"
/dev/mmcblk0p2: LABEL="rootfs" UUID="7295bbc3-bbc2-4267-9fa0-099e10ef5bf0" TYPE="ext4" PARTUUID="15a061d1-02"
/dev/mmcblk0: PTUUID="15a061d1" PTTYPE="dos"
可以看到,boot分区的PARTUUID=“15a061d1-01”,rootfs分区的PARTUUID=“15a061d1-02”。
系统启动时,需要从 /boot/cmdline.txt 中加载root分区,并且需要通过 /etc/fstab 正确挂载文件系统分区rootfs。需确保上述两个文件中的uuid部分一致。
pi@raspberrypi:~ $ cat /boot/cmdline.txt
console=tty1 root=PARTUUID=15a061d1-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
pi@raspberrypi:~ $ cat /etc/fstab
proc /proc proc defaults 0 0
PARTUUID=15a061d1-01 /boot vfat defaults 0 2
PARTUUID=15a061d1-02 / ext4 defaults,noatime 0 1
# a swapfile is not a swap partition, no line here
# use dphys-swapfile swap[on|off] for that
如果partuuid配置不正确,可以先将tf卡挂载在其他linux下查看uuid,再通过mount修改对应文件。
或者使用后一节的方式。
3、分区的 PARTUUID
前面不能启动的原因,是因为我们制作新的tf卡系统时,分区的partuuid发生了变化,但是 /boot/cmdline.txt 以及 /etc/fstab 中的内容还是源系统中的partuuid,因为文件是直接复制的。本节不修改这些文件内容,而是修改分区partuuid。
3.1、linux下使用fdisk修改
在linux系统下,放入一个不能正常启动的tf系统卡,挂载后查看分区信息、文件信息
pi@raspberrypi:~ $ sudo blkid | grep sd
/dev/sda1: LABEL_FATBOOT="boot" LABEL="boot" UUID="7581-8A48" TYPE="vfat" PARTUUID="c2dfa3eb-01"
/dev/sda2: LABEL="rootfs" UUID="fa37d505-e741-4d35-bcec-4580aef395e1" TYPE="ext4" PARTUUID="c2dfa3eb-02"
pi@raspberrypi:~ $ cat boot_dir/cmdline.txt
console=tty1 root=PARTUUID=e8f831da-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
pi@raspberrypi:~ $ cat root_dir/etc/fstab
proc /proc proc defaults 0 0
PARTUUID=e8f831da-01 /boot vfat defaults 0 2
PARTUUID=e8f831da-02 / ext4 defaults,noatime 0 1
可以看到,当前插入的tf卡的分区PARTUUID为"c2dfa3eb",但是文件中要求分区PARTUUID为"e8f831da",因此需要将当前分区PARTUUID从"c2dfa3eb"修改为"e8f831da"。直接使用fdisk
工具即可,先用命令p
查看分区信息,可以看到"Disk identifier: 0xc2dfa3eb"
,十六进制的字符就是当前分区的PARTUUID。命令x
进入专家模式,命令i
修改,输入十六进制字符串"0xe8f831da",命令r
返回主命令界面后使用命令w
保存。
pi@raspberrypi:~ $ sudo fdisk /dev/sda
Welcome to fdisk (util-linux 2.33.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): p
Disk /dev/sda: 29.7 GiB, 31914983424 bytes, 62333952 sectors
Disk model: Storage Device
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xc2dfa3eb
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 8192 532479 524288 256M b W95 FAT32
/dev/sda2 532480 6553599 6021120 2.9G 83 Linux
Command (m for help): x
Expert command (m for help): i
Enter the new disk identifier: 0xe8f831da
Disk identifier changed from 0xc2dfa3eb to 0xe8f831da.
Expert command (m for help): r
Command (m for help): w
The partition table has been altered.
Syncing disks.
重新查看,修改成功。
pi@raspberrypi:~ $ sudo blkid | grep sd
/dev/sda1: LABEL_FATBOOT="boot" LABEL="boot" UUID="7581-8A48" TYPE="vfat" PARTUUID="e8f831da-01"
/dev/sda2: LABEL="rootfs" UUID="fa37d505-e741-4d35-bcec-4580aef395e1" TYPE="ext4" PARTUUID="e8f831da-02"
当前卡作为系统卡启动,正常。
3.1、windows下使用diskpart修改
在windows下,我们将上面修改过的td卡插入win系统,使用diskpart修改partuuid,win+R,cmd,diskpart进入命令行。
DISKPART> list disk
磁盘 ### 状态 大小 可用 Dyn Gpt
-------- ------------- ------- ------- --- ---
磁盘 0 联机 476 GB 5120 KB *
磁盘 1 联机 931 GB 1024 KB *
磁盘 2 联机 29 GB 24 GB
DISKPART> select disk2
磁盘 2 现在是所选磁盘。
DISKPART> detail disk
Mass Storage Device USB Device
磁盘 ID: C2DFA3EB
类型 : USB
状态 : 联机
路径 : 0
目标 : 0
LUN ID : 0
位置路径 : UNAVAILABLE
当前只读状态: 否
只读: 否
启动磁盘: 否
页面文件磁盘: 否
休眠文件磁盘: 否
故障转储磁盘: 否
群集磁盘 : 否
卷 ### LTR 标签 FS 类型 大小 状态 信息
---------- --- ----------- ----- ---------- ------- --------- --------
卷 8 G boot FAT32 可移动 256 MB 正常
可以看到磁盘 ID: C2DFA3EB
,正是修改过的。使用命令"set uniqueid
"修改磁盘ID,例如修改成"E8F831DA",之后再次查看,修改成功。
DISKPART> uniqueid disk id=E8F831DA
DISKPART> detail disk
Mass Storage Device USB Device
磁盘 ID: E8F831DA
类型 : USB
状态 : 联机
路径 : 0
目标 : 0
LUN ID : 0
位置路径 : UNAVAILABLE
当前只读状态: 否
只读: 否
启动磁盘: 否
页面文件磁盘: 否
休眠文件磁盘: 否
故障转储磁盘: 否
群集磁盘 : 否
卷 ### LTR 标签 FS 类型 大小 状态 信息
---------- --- ----------- ----- ---------- ------- --------- --------
卷 8 G boot FAT32 可移动 256 MB 正常
DISKPART>
4、使用Win32ImgManager / dd备份、pishrink.sh压缩(最简单的方式)
4.1、备份tf中的系统为img镜像
将需要备份系统的tf插入电脑,使用Win32ImgManager进行读取操作保存为img到本地磁盘上,同linux下使用dd命令类似。保存后的文件比较大,大小同tf卡的容量。
树莓派系统下,直接使用命令 dd bs=4M if=/dev/mmcblk0 of=test.img
,等待结束即可(先要执行 sudo ./rpiboot
将树莓派识别为usb设备,参看《树莓派计算模块CM4 eMMC系统烧写、配置、相机连接》)。
4.2、调整img文件大小
当前我们备份的系统img镜像大小为16G左右。将镜像放在linux下,使用pishrink.sh脚本执行命令sudo ./pishrink.sh -s test.img raspipos_shrink.img
(这里的-s表示第一次启动不进行文件系统扩展,后续可能需要手动扩容),运行结果为
pi@raspberrypi:~ $ sudo ./pishrink.sh -s test.img raspipos_shrink.img
pishrink.sh v0.1.2
pishrink.sh: Copying test.img to raspipos_shrink.img... ...
pishrink.sh: Gathering data ...
Skipping autoexpanding process...
pishrink.sh: Checking filesystem ...
rootfs: recovering journal
rootfs: 72076/949104 files (0.3% non-contiguous), 915995/3822976 blocks
resize2fs 1.44.5 (15-Dec-2018)
pishrink.sh: Shrinking filesystem ...
resize2fs 1.44.5 (15-Dec-2018)
Resizing the filesystem on /dev/loop0 to 1108704 (4k) blocks.
Begin pass 2 (max = 111809)
Relocating blocks XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 3 (max = 117)
Scanning inode table XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 4 (max = 8772)
Updating inode references XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The filesystem on /dev/loop0 is now 1108704 (4k) blocks long.
pishrink.sh: Shrinking image ...
pishrink.sh: Shrunk raspipos_shrink.img from 15G to 4.5G ...
img文件压缩为大小为4.5G。进一步,可以使用命令zip raspipos_shrink.img.zip raspipos_shrink.img
进行压缩,三个文件的大小如下
pi@raspberrypi:~ $ ls -l
-rwxr-xr-x 1 pi pi 10904 Nov 20 14:07 pishrink.sh
-rw-r--r-- 1 pi pi 4813881856 Nov 20 15:30 raspipos_shrink.img
-rw-r--r-- 1 pi pi 1724249564 Nov 20 15:58 raspipos_shrink.img.zip
-rw-r--r-- 1 pi pi 15931539456 Nov 20 15:12 test.img
脚本pishrink.sh参数说明
Usage: $0 [-adhrsvzZ] imagefile.img [newimagefile.img]
-s Don't expand filesystem when image is booted the first time
-v Be verbose
-r Use advanced filesystem repair option if the normal one fails
-z Compress image after shrinking with gzip
-Z Compress image after shrinking with xz
-a Compress image in parallel using multiple cores
-d Write debug messages in a debug log file
4.3、系统卡制作测试
直接将raspipos_shrink.img通过Win32ImgManager写入到新的tf卡中。linux下的脚本为sudo dd if=raspberry.img of=/dev/sdX bs=4M conv=fsync
,其中/dev/sdx是插入的tf卡设备。
不同于上面使用DiskGenius的按文件复制后需要修改partuuid,这里的方式可以直接运行开机。
但是不同于官方img,磁盘的可用空间不是特别大,根据需需要开机手动进行扩容操作。或者再系统卡制作后先手动进行扩容,例如windows下使用DiskGenius的调整分区大小、扩容分区功能,如下
当然,也可以进入系统后,使用sudo raspi-config扩容;可以去掉pishrink.sh脚本执行时使用的-s参数,见前章节。