我有一个使用 Ubuntu 实例拍摄的原始磁盘映像dd
。总磁盘大小为300 GB, 但只有5.5 GB用过的。
有没有办法将原始 dd 图像的大小调整为20 GB,保留所有 5.5 GB 的数据,只截断空块?
答案1
检查扇区大小:
sudo fdisk -l '/home/user/images/test.img'
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: 0x00070424
Device Boot Start End Sectors Size Id Type
/home/user/images/test.img1 * 2048 26623 24576 12M e W95 FAT16
/home/user/images/test.img2 26624 7200767 7174144 3,4G 83 Linux
使用结束号码(7200767)作为参考添加 1 和 * 512 如下所示:
sudo truncate --size=$[(7200767+1)*512] '/home/user/images/test.img'
您的文件应该被截断
答案2
由于它是原始图像,因此它的尺寸始终与您制作的实例完全相同。但是,您可以使用一些技巧来实现相同的效果。
调零
将零写入未使用空间的区域,为压缩做好准备,从而有效地将大小减小到小于已用空间:
sudo mount -o loop instance.img /testmount
sudo dd if=/dev/zero of=/testmount/zero
sudo rm -f /testmount/zero
sudo umount /testmount
压缩
无论您是否先将其归零,只需压缩图像即可使其变小:
gzip instance.img
或者,采用更现代的方法:
zstd -T0 instance.img
文件系统感知映像
如果映像不必是原始的(即块设备而不是内容的表示),您还可以选择使用文件系统感知工具来创建映像。在这种情况下不需要归零。例如,ZFS 内置了对此的支持,例如压缩:
sudo zfs snapshot myvms/myinstance@myimage
sudo zfs send myvms/myinstance@myimage | zstd -T0 > instance.zfs.zst
答案3
如果磁盘是 GPT 分区,truncate
@Wessel 给出的选项会导致请求表条目损坏,并且该文件无法用作循环设备。我按照这个方法
- 首先将磁盘映像挂载为循环设备
sudo -i
udisksctl loop-setup -f disk.img
#notedown where its mounted
gparted /dev/loopxx
- 在 gparted UI 中,在末尾添加一个 1MB 大小的新分区,应用更改
- 卸载文件
udisksctl loop-delete -b /dev/loopxx
- 将分区表转储到文件中
sfdisk -d disk.img > partitions.txt
- 查找最后使用的扇区
parted disk.img 'unit s print'
- 查找字节偏移量 = (最后使用的扇区 + 1)* 512
- 截断文件
truncate -s offset disk.img
- 更新partitions.txt以反映新状态
Remove the last-lba line from the since it no longer valid
Remove last 1MB partition since we don't need it anymore
- 恢复分区表
sfdisk disk.img < partitions.txt