调零

调零

我有一个使用 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 给出的选项会导致请求表条目损坏,并且该文件无法用作循环设备。我按照这个方法

  1. 首先将磁盘映像挂载为循环设备
sudo -i
udisksctl loop-setup -f disk.img
#notedown where its mounted
gparted /dev/loopxx
  1. 在 gparted UI 中,在末尾添加一个 1MB 大小的新分区,应用更改
  2. 卸载文件udisksctl loop-delete -b /dev/loopxx
  3. 将分区表转储到文件中sfdisk -d disk.img > partitions.txt
  4. 查找最后使用的扇区parted disk.img 'unit s print'
  5. 查找字节偏移量 = (最后使用的扇区 + 1)* 512
  6. 截断文件truncate -s offset disk.img
  7. 更新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
  1. 恢复分区表sfdisk disk.img < partitions.txt

相关内容