将内存卡的 Armbian 迁移到其它内存卡
家里有一台「Orange PI Zero」用于提供一些内网服务。因为旧卡只是一个普通的 Class 10 卡,最大写入速度为 10 MB/s,在执行
apt update
或 apt upgrade
指令时会… 非常的慢。
※ 任何恢复操作前都需要备份。备份前请腾出空间用于储存备份数据。
※ 这篇文章是实际操作后的复盘记录。我会尽量保持文章的一致性,如果发现错误请报告。
准备工作
本文的设备名如下:
- 旧卡设备是
/dev/sdb
- 新卡设备是
/dev/sdc
你需要准备的工具:
- 压缩指令
zstd
,解压输出指令zstdcat
。- 如果没有,可以分别替换为
gzip
和zcat
。
- 如果没有,可以分别替换为
- 备份工具
partclone
- 底层数据读写
dd
- (可选) 挂载文件用但不适合恢复的
squashfs
,用于提取文件
备份
备份系统分区
因为不想用 DD 把使用和未使用的分区数据都拷贝了,因此分别用 partclone
1 来进行分区备份还原。
sudo partclone.ext4 -c -s /dev/sdb1 | zstd > opi_working_20230721.pcl.zst
得到备份文件,看看大小:
$ ls -lh opi_working_20230721.pcl.zst | cut -f5 -d' '
264M
$ zstdcat opi_working_20230721.pcl.zst | wc -c
987993258 (约 942.2 MB)
zstd
的压缩率还是很可观的,差不多 28%。
归档 (方便文件访问)
因为我不希望一直将内存卡挂载在电脑上,因此我还用 squashfs
打了一个备份,方便挂载查看文件。如果不需要,可以跳过。
其中 -mem 8G
用来指定存档压缩时最多可占用的内存大小。可以根据你的系统来调节:
# squashfs 是对分区内的文件进行打包
sudo mount /dev/sdb1 /mnt
sudo mksquashfs /mnt opi_working_20230721.squashfs \
-not-reproducible \
-xattrs \
-noappend \
-progress \
-mem 8G
# 可以取消挂载了
sudo umount /mnt
挂载的话也是非常简单:
sudo mkdir -p /storage/orangepi_root_old
sudo mount -t squashfs -o ro -o loop \
opi_working_20230721.squashfs \
/storage/orangepi_root_old
备份引导
Armbian 其实还在文件头写出了一个小引导(还有一些 MBR 信息),先照抄过来。
$ sudo fdisk -l /dev/sdb | tee opi_working_20230721.partition_table.txt
Disk /dev/sdb: 14.46 GiB, 15523119104 bytes, 30318592 sectors
Disk model: USB3.0 CRW -SD
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: 0x940fc01d
Device Boot Start End Sectors Size Id Type
/dev/sdb1 8192 29982720 29974529 14.3G 83 Linux
可以看到第一个分区在扇区偏移 8192
处,因此使用 dd
来拷贝这部分的数据:
sudo dd if=/dev/sdb of=opi_working_20230721.header.bin bs=512 count=8192
可以使用 xxd
观察,可以发现从字节偏移 0x2000
处开始有引导代码2:
00002000: 1600 00ea 6547 4f4e 2e42 5430 ed4e 3a0c ....eGON.BT0.N:.
00002010: 0060 0000 5350 4c02 0000 0000 0000 0000 .`..SPL.........
00002020: 2c00 0000 0000 0000 0000 0000 7375 6e38 ,...........sun8
00002030: 692d 6832 2d70 6c75 732d 6f72 616e 6765 i-h2-plus-orange
00002040: 7069 2d7a 6572 6f00 0000 0000 0000 0000 pi-zero.........
00002050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
还原
恢复引导
※ 该操作会干掉你的分区信息。如果需要,请先备份硬盘数据。
直接将备份的设备头信息写出到新的设备 /dev/sdc
即可:
sudo dd if=opi_working_20230721.header.bin of=/dev/sdc oflag=direct
修复分区表
另外因为第一个扇区是 MBR 信息,因此恢复引导的时候也把分区表给拷贝了。
如果是拷贝到新的内存卡,则需要手动修复下:
- 执行
sudo fdisk /dev/sdc
编辑分区表- 指令:
d
- 删除第一个分区- 若询问分区序号,则键入
1
后回车 - 重复删除直到没有分区。
- 若询问分区序号,则键入
- 指令:
n
- 新建一个分区- 询问类型 - 键入
p
后回车,使用主要分区 - 询问序号 - 键入
1
后回车,使用第一个主分区 - 询问起始扇区 - 键入
8192
后回车 (同备份的分区扇区偏移) - 询问终止扇区 - 直接回车,使用内存卡最终的位置 (你也可以使用
-4M
不使用结尾的部分储存)。 - 若询问是否擦除分区标记 - 选择
Y
或N
都可以。
- 询问类型 - 键入
- 指令:
t
- 修改分区类型- 若询问分区序号,则键入
1
后回车 - 询问分区类型,键入
83
后回车 (代表Linux
分区)
- 若询问分区序号,则键入
- 指令:
p
- 预览要应用的分区更改。- 若预览看起来不对劲,键入指令
q
并回车来放弃更改并退出
- 若预览看起来不对劲,键入指令
- 指令:
w
- 写出分区表更改
- 指令:
操作过程查看
$ sudo fdisk /dev/sdc
Welcome to fdisk (util-linux 2.39.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): d
Selected partition 1
Partition 1 has been deleted.
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-30318591, default 2048): 8192
Last sector, +/-sectors or +/-size{K,M,G,T,P} (8192-30318591, default 30318591):
Created a new partition 1 of type 'Linux' and of size 14.5 GiB.
Partition #1 contains a ext4 signature.
Do you want to remove the signature? [Y]es/[N]o: N
Command (m for help): t
Selected partition 1
Hex code or alias (type L to list all): 83
Changed type of partition 'Linux' to 'Linux'.
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
还原分区
然后使用 partclone
来还原:
zstdcat opi_working_20230721.pcl.zst | sudo partclone.ext4 -r -s - -o /dev/sdc1
检查分区
还原完后,先跑个检查:
sudo fsck /dev/sdc1
如果发生错误,建议检查原始设备是否也有问题。可以尝试在 fsck
进行修复。
(跑题) 内存卡读写测速
测试指令:
# 测试写
sudo dd if=/dev/zero of=./__test.img bs=1M count=256 oflag=direct status=progress
# 测试读
sudo dd of=/dev/zero if=./__test.img bs=1M count=256 iflag=direct status=progress
- 旧卡 (脱机读写):写
7.2 MB/s
读51.3 MB/s
- 新卡 (在线读写):写
20.8 MB/s
读23.5 MB/s
嗯… 虽然说翻了一倍,但其实和声称的 50MB/s 还是差了些的。拔下来脱机跑看看。
- 新卡 (脱机读写): 写
51MB/s
读92.6 MB/s
看来限制是在单片机自身上了,那也没办法了… 有可能和供电不足有关?毕竟我为了省事是直接从路由器的 USB 口接的电源。
文档参考 Partclone: manual | partclone.restore ↩︎
可以参考全志 sunxi 百科 的引导说明。 ↩︎