语境
我有一个 16 GB 的 SD 卡,带有用于 Raspberry Pi 的基于 Linux 的操作系统。大部分空间是空的。
我想.img
与其他人共享 SD 但如果我使用命令
dd if=/dev/sdXX of=/home/user123/SD.img
它将创建一个 16 GB 的图像。太大。
问题
如何将 16GB SD 卡映像重新调整为更小的 4GB?
我已经尝试过使用 GParted:它可以毫无问题地创建一个 4GB 的分区,但是整个.img
SD 卡仍然是 16 GB 和 12 GB 的未分配空间。
我已经阅读了在 Ubuntu 中克隆多个分区的问题和答案,但我仍然无法将 16GB SD 卡的大小重新调整为 4GB 的。
更多信息
~$ lsblk
...
sdc 8:32 1 14,9G 0 disk
├─sdc1 8:33 1 100M 0 part
└─sdc2 8:34 1 4G 0 part
~$ sudo fdisk -l /dev/sdc
Disk /dev/sdc: 14,9 GiB, 15931539456 bytes, 31116288 sectors
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: 0xf8a631ce
Device Boot Start End Sectors Size Id Type
/dev/sdc1 * 2048 206847 204800 100M c W95 FAT32 (LBA)
/dev/sdc2 206848 8595455 8388608 4G 83 Linux
任何建议表示赞赏!
请注意:正如 Melebius 在评论中所观察到的,正确使用的词是收缩:
您无法调整 SD 卡的大小,因为它是具有给定容量且无法更改的硬件。您显然想要缩小 SD 卡映像。
本文给出了解决我的问题的解决方案(*)。它与另一个非常相似,但它更好地解释了如何计算以及数字和分区的含义。
关键信息是命令的使用
truncate
。遵循完整的解决方案,以免丢失答案。初步步骤包括在您的 PC 中克隆 SD 卡:
用于
lsblk
查看哪些设备可用以及它们的分区是否已挂载卸载要在 PC 上复制的设备的所有分区。例如:
创建整个 SD 卡的副本,其中所有分区都已卸载
在 Linux 上缩小图像
问题的背景:
拥有
myimage.img
更大的硬件支持(如果它更小应该没有问题;但是,使用相同的策略,您可以更好地使图像适合硬件支持)。秘诀是使用标准的 Linux 工具和工具:GParted
fdisk
和truncate
.要求:
.img
你想要缩小的(myimage.img
在这个例子中)创建环回设备:
GParted 是一个通常用于管理分区表和文件系统的应用程序。为了缩小图像,将在答案的第一部分使用 GParted。
让我们启用环回:
让我们请求一个新的(免费)环回设备:
该命令返回到空闲环回设备的路径:
让我们创建一个图像的设备:
该设备
/dev/loop0
代表myimage.img
. 我们想要访问映像上的分区,所以我们需要让内核也加载这些分区:这应该给我们设备
/dev/loop0p1
,它代表 中的第一个分区myimage.img
。我们并不直接需要这个设备,但 GParted 需要它。使用 GParted 调整分区大小:
让我们使用 GParted 加载新设备:
当 GParted 应用程序打开时,它应该会出现一个类似于以下内容的窗口:
现在注意几点:
我们想调整这个分区的大小,使其适合其内容,但仅此而已。
选择分区并单击调整大小/移动。将弹出一个类似于以下的窗口:
将右栏尽可能向左拖动。
请注意,有时 GParted 需要额外的几 MB 来放置一些与文件系统相关的数据。您可以按几次新尺寸框上的向上箭头来执行此操作。例如,我按了 10 次 (=10MiB) 以使 FAT32 工作。对于 NTFS,您可能根本不需要。
最后按调整大小/移动。您将返回到 GParted 窗口。这次它看起来类似于以下内容:
请注意,有一部分磁盘未分配。这部分磁盘不会被分区使用,因此我们可以稍后将这部分从映像中剔除。GParted是一个磁盘工具,所以它不收缩镜像,只有分区,我们必须自己做镜像的收缩。
按ApplyGParted。它现在将移动文件并最终缩小分区,因此可能需要一两分钟,但大多数情况下它会很快完成。然后关闭 GParted。
现在我们不再需要 loopback-device 了,所以卸载它:
剃须图像:
现在我们在图像的开头有了所有重要的数据,是时候去掉那些未分配的部分了。我们首先需要知道我们的分区在哪里结束以及未分配部分从哪里开始。我们使用
fdisk
:在这里,我们将看到类似于以下的输出:
注意输出中的两件事:
End
)1 * 512
)我们将在示例的其余部分中使用这些数字。块大小 (512) 通常是相同的,但结束块 (9181183) 会因您而异。这些数字表示分区在文件的字节 9181183 512 处结束。在那个字节之后是未分配部分。只有前 9181183 512 个字节对我们的图像有用。
接下来,我们将图像文件缩小到可以包含分区的大小。为此,我们将使用
truncate
命令(感谢 uggla!)。使用 truncate 命令需要以字节为单位提供文件的大小。最后一个块是 9181183,块号从 0 开始。这意味着我们需要 (9181183+1)*512 字节。这很重要,否则分区将不适合图像。所以现在我们使用 truncate 进行计算:(*) FrozenCow 的原帖好像已经移到这里了。
您可以使用选项
bs
和-command 来限制输出文件count
的dd
大小。例子:
将产生一个大小为 4 GiB 的输出文件。
深入了解
man dd
.您需要知道必须复制多少字节才能完全覆盖所有分区,因此请查看
sudo fdisk -l /dev/sdx
哪个扇区是您需要的最后一个扇区。分区需要位于磁盘的开头(如您提供的图片中所示)。
带有 msdos-partition-table 的磁盘可以通过这种方式轻松克隆,但是如果磁盘使用 GPT 并且要克隆到不同大小的磁盘,则需要调整保护性 MBR 和驻留在最需要重新创建磁盘的末尾,这可以使用
gdisk
.从你的
fdisk
-output 你可以看到最后一个分区的最后一个扇区是扇区8595455
,这意味着你必须复制至少 8595455+1 个扇区(第一个扇区是 0)。对于 512 字节的扇区大小,这等于 4,400,873,472 字节。bs
乘以count
必须大于或等于此。也许这对于一个 4GB 的 U 盘来说还是太大了,你仍然可以减小它的大小
sdc2
,里面还有很多未使用的空间。对于您提供的当前示例,
将覆盖分区表,
sdc1
并且sdc2
. 计算:resize2fs
也可以用来调整它的大小。它还会调整文件本身的大小!
所选答案完全适用于dos disklabel 类型。对于GPT类型,需要考虑添加 33 个扇区,因为 GPT 在磁盘末尾也存储了一张表。
因此,对于 GPT 用户,“截断”命令需要如下所示:
截断 --size=$[( End_of_last_partition + 1 + 33 )*512] myimage.img
这应该会在
fdisk -l
. 要解决此问题,请运行以下命令:运行命令以验证磁盘:
v
. 您应该会在磁盘上看到一些错误。“在 gdisk 中,你可以输入x进入专家菜单,然后输入e将备份分区表数据移动到磁盘的新端,然后输入w将更改写入磁盘。” [来源]如何在不损坏 GPT 分区表(结束指针)的情况下截断未使用空间的磁盘映像文件- 谢谢!
浏览了这里的许多方法,我理解了所有这些方法,但这些步骤是我不期待的,因为必须依次执行它们以简单地缩小 Raspberry Pi IMG 文件。因此,我从一个名为PiShrink的项目中发现了这个 Bash 脚本。
执行起来非常简单,它可以在我的 MacOS M1 Mac Mini 上启动。
背景故事
在我的特殊情况下,我有 2 个 32GB SD 卡,无论出于何种原因,1 比另一个稍小(~95MB),balenaEtcher拒绝将 IMG 从 2 个 SD 卡中的较大者写入较小的部分。
我知道我只使用了 32GB 中的约 10GB,所以我可以缩小 IMG 文件以适应。
脚步
首先,我有以下文件。该
.zip
文件包含该.img
文件,但我在下面显示它是从它解压缩的。然后我下载了 PiShrink shell 脚本并使其可执行:
然后我像这样运行它:
生成的 IMG 文件现在约为 9GB。
然后我将它重新打包为 ZIP 文件,以便在磁盘上处理它时尽可能保持最有效的大小。
我们现在有以下一组文件:
然后我可以使用balenaEtcher或ApplePi-Baker将 ZIP 文件刻录到“较小”的 SD 卡上。
在我的 Mac 上戳 SD 卡,我可以看到它显示 ~10GB。
注意:我可以使用
lsblk
等从 Linux 系统执行相同的命令。后期操作
使用上述方法后,我确实注意到 SD 卡中的文件系统不足 32GB。主要是这样显示的:
启动备份后,通过从内部扩展 SD 文件系统应该可以轻松解决此问题。
首先,我首先使用
parted
扩展分区:然后我重新启动了系统:
在我使用以下方法在线扩展文件系统之后
resize2fs
:现在它显示了 SD 卡上的所有可用空间: