前天打算在 Raspberry Pi Zero W 的存储卡中,开辟出一块 Fat32 分区,以便与 Windows 进行数据交换。
不过,系统的 Ext4 分区已经把剩下的空间占满了。所以必须要先调整 Ext4 分区的大小。
以前也做过类似的操作,不过上次是用 DiskGenius ,一款部分功能(比如写入 Ext 分区)收费的软件。本着对开源软件的偏爱,于是想着能不能用 DiskGenius 以外的方法解决。
只需要 cfdisk ... 吗?
网上看到很多使用 fdisk 的教程。虽然它是交互式命令行应用,不过还是有点复杂。寻寻觅觅,找到了 cfdisk 。它的 TUI 还是十分直观的,上手使用轻轻松松。

于当时的我来说,这便是银弹了。遂将 Ext4 分区调整至10GB (虽然没有统计过重新分配前的根目录大小,但是我知道不会超过这个数值),然后剩下的空间都分配给 Fat32 分区。调整完,有个 Write 选项,上面有一行字说将分区表写入到硬盘,以及警告可能损坏数据。我觉得这样操作也没什么问题,就保存了。
然后用 mkfs.vfat 给新分区格式化,顺便用 fstab 给新分区添加自动挂载。关机,把卡拔出来插到读卡器,在 Windows 环境下顺利发现了新的 Fat32 分区,于是我往里面放了几个文件,读写十分正常。
看起来,似乎没有什么问题。但是数据丢失的惨案已经发生了。
cfdisk 只能更改分区表!
第二天我把卡重新插回树莓派,发现无法正常启动。我想可能是 fstab 配置写错了。于是在 Linux 环境下读取卡中数据。结果挂载卡中 Ext4 分区时报错了,有点慌了,想到在保存分区表时的警告,可能是把它写坏了。
在 Google 上搜索(计算机技术问题用谷歌是好习惯),找到了这条帖子:“How to recover data from resized partition? [Solved]”。
To shrink a EXT2/3/4 partition, one must first use resize2fs to shrink the filesystem, then, change the partition table to match the new size. Using cfdisk alone would have only altered the partition table. Your great mistake is to have run mkfs.ext4 on the new partition sda4. Some of your data was likely overwritten on disk, as seth said above.
要减小一个 Ext2/3/4 分区的容量,你必须先使用
resize2fs来收缩分区。然后,更改分区表,以与新的容量相匹配。只用cfdisk更改的仅仅是分区表(译注:即分区内的数据没有被收缩到新的范围内)。你最大的错误是在新的 "sda4" 分区格式化了 Ext4 文件系统,硬盘上的有些数据已经被覆写了。
看了回复,算是豁然开朗了。就像这条帖子中另外一个回复,在 Ext 分区中的数据并不是连续存储的(别的文件系统我就不知道了),它们分散在这个分区的每个角落。仅更改分区表,将会使新的分区与上个分区数据的范围重叠,也就意味着覆写已经埋下伏笔。我原以为 cfdisk 会像 DiskGenius 一样在重新调整大小前会自己移动数据到合适的位置,结果我没想到它只能更改分区表。
数据,我已经救不回来了。我没有备份分区表,在重新分配之后还格式化了新分区,还往里面写了一堆数据,原来分区内的数据肯定被覆写了。
正确方法:resize2fs
万幸的是这张卡里没什么重要的东西,我只需要重新刷个系统,重新部署原来的应用即可。于是花了我一个多小时把它弄成原来的样子。
当然,我也没有忘记原来要干的事情。这次我先运行 resize2fs 来调整 Ext4 分区的数据。
resize2fs /dev/mmcblk0p7 10G
然后运行 cfdisk ,调整分区表与上面的调整吻合即可。
一次撞墙的经历... 虽然用 DiskGenius 就能简单搞定,但是谁让我喜欢折腾更加 geek 的解决方案呢...