本文使用losetup 和 rsync生成基于原始镜像的自定义镜像用于备份或量产,该方法仅用于实验测试用途。
!!!先看缺点!!!
!!!先看缺点!!!
!!!先看缺点!!!
!!!先看缺点!!!
!!!先看缺点!!!
!!!先看缺点!!!
!!!先看缺点!!!
!!!先看缺点!!!
准备步骤:
- Ubuntu机器
- 开发板
- 同一局域网
操作方法:
- 假设开发板上烧录一个名为image.img的镜像(可以是自己编译的或者其他人编译的镜像)并完成了自定义配置,使用Ubuntu系统的losetup命令将img镜像文件挂载到loop设备上。不同镜像的boot分区和rootfs分区可能会有些许差异,建议先使用lsblk查看分区结构。下面将展示一个使用orangepi-build编译的镜像挂载到WSL的Ubuntu上面的示例:
使用sudo losetup -fP xxx.img
自动挂载镜像到设备可用的loop设备上。使用lsblk可以看到这个镜像分为loop0p1 和 p2两个分区
在开发板上查看lsblk可以看到两个分区分别对应boot和rootfs
在WSL上创建两个文件夹用于挂载这两个分区。
使用mount命令挂载
然后在WSL上直接使用rsync同步开发板上的文件系统到挂载的镜像中完成备份量产。完成后的镜像可直接烧录。
下面是使用rsync从ssh同步的命令
sudo rsync -avz --delete --progress -e "ssh -o StrictHostKeyChecking=no" root@{ip}:/boot/ ./p1/
sudo rsync -aAXvz --delete --progress -e "ssh -o StrictHostKeyChecking=no" --exclude={"/dev/","/proc/","/sys/","/tmp/","/run/","/mnt/","/media/*","/lost+found"} root@{ip}:/ ./p2/
该方法缺点:
需要手动扩容
- 大小受到原始镜像限制。使用
parted xxx.img print
查看镜像最大容量。如下图这个镜像最大为8791MB,从开发板同步到镜像里面的文件如果让原镜像超过了8791MB则无法进行备份需要对镜像进行扩充并重写分区表
方法如下: - 使用
truncate -s 12G xxx.img
扩充镜像大小,这里是扩到12G - 使用
sudo parted xxx.img print
查看分区信息,会弹出自动修复提示,输入F自动修复 - losetup挂载镜像到loop设备,然后使用parted命令对该镜像进行分区修改
sudo parted /dev/loop0
print
查看分区信息
rm 2
删除rootfs分区信息(该操作只会修改分区表信息,并不会对实际的存储造成任何影响)
mkpart rootfs ext4 1105MB 100%
使用mkpart创建分区,该分区最好与原来分区的Name保持一致,原来叫rootfs这里最好也是rootfs
quit
退出parted
sudo e2fsck -f /dev/loop0p2
检查分区是否有故障
sudo resize2fs /dev/loop0p2
扩容分区
sudo losetup -d /dev/loop0
断开loop设备,完成扩容
扩容后如下图
烧录后系统分区容量不会根据开发板上存储设备自动适配
可以看到烧录完之后64GB的EMMC分区只占到镜像的大小,对应分区没有自动扩容
解决方法:使用chroot进入挂载在loop设备的img镜像系统,配置自动扩容的脚本。下面是手动的方式,具体设备名根据实际修改
# 安装 growpart(若未安装)
sudo apt install cloud-guest-utils # Debian/Ubuntu
# 扩展最后一个分区(假设是 /dev/mmcblk0p2)
sudo growpart /dev/mmcblk0 2 # 注意:设备名和分区号之间要有空格!
# 扩展 ext4 文件系统(假设是 /dev/mmcblk0p2)
sudo resize2fs /dev/mmcblk0p2
下面是ch-mount.sh脚本内容,将内容复制保存为一个可执行的ch-mount.sh文件
使用方法:
./ch-mount.sh -m {rootfs_dir} #挂载并进入chroot模式
退出chroot模式按下Ctrl+D
./chmount.sh -u {rootfs_dir} #卸载
#!/bin/bash
function mnt() {
echo "MOUNTING"
sudo mount -t proc /proc ${2}proc
sudo mount -t sysfs /sys ${2}sys
sudo mount -o bind /dev ${2}dev
sudo mount -o bind /dev/pts ${2}dev/pts
sudo chroot ${2}
}
function umnt() {
echo "UNMOUNTING"
sudo umount ${2}proc
sudo umount ${2}sys
sudo umount ${2}dev/pts
sudo umount ${2}dev
}
if [ "$1" == "-m" ] && [ -n "$2" ] ;
then
mnt $1 $2
elif [ "$1" == "-u" ] && [ -n "$2" ];
then
umnt $1 $2
else
echo ""
echo "Either 1'st, 2'nd or both parameters were missing"
echo ""
echo "1'st parameter can be one of these: -m(mount) OR -u(umount)"
echo "2'nd parameter is the full path of rootfs directory(with trailing '/')"
echo ""
echo "For example: ch-mount -m /media/sdcard/"
echo ""
echo 1st parameter : ${1}
echo 2nd parameter : ${2}
fi