Answers:
首先,请确保可用空间实际上是空的,并且不包含已删除文件的剩余空间。实现此目的的最简单方法是在磁盘上创建一个仅包含空字节的巨大文件,然后将其删除。
# losetup --find --partscan foo.img
# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 4096M 0 loop
├─loop0p1 259:0 0 2048M 0 loop
└─loop0p2 259:1 0 2048M 0 loop
# for part in /dev/loop0p*; do
mount $part /mnt
dd if=/dev/zero of=/mnt/filler conv=fsync bs=1M
rm /mnt/filler
umount /mnt
done
dd: error writing ‘/mnt/filler’: No space left on device
dd: error writing ‘/mnt/filler’: No space left on device
# losetup --detach /dev/loop0
然后使用诸如gzip
或的工具将其压缩xz
。即使在最低压缩级别下,一连串的零也会很好地压缩:
# ls -s
4096M foo.img
# gzip foo.img
# ls -s
11M foo.img.gz
请注意,将映像写回到磁盘时必须解压缩映像。这将“实时”解压缩:
# cat foo.img.gz | gunzip | dd of=/dev/sda
请注意,输出设备(sda)的大小必须足以容纳原始图像,否则数据将丢失或损坏。
如果要继续使用该映像(例如与虚拟机一起使用),另一种方法是将原始映像转换为虚拟化软件使用的一种映像格式。例如,用于Qemu的qcow2,用于VirtualBox的VDI或用于VMware的VMDK。
请注意,这仍然需要您使用上述方法通过清洁可用空间来准备图像。
# qemu-img convert -f raw -O qcow2 foo.img foo.qcow
# qemu-img convert -f raw -O vmdk foo.img foo.vmdk
但是,如果要将其再次写入实际磁盘,则必须将其转换回原始映像。
resize2fs
或ntfsresize
(Linux没有FAT工具),或者通过创建新的文件系统并仅复制文件来进行调整。
使用resize2fs
要容易得多
resize2fs -M xxx.img
您将被要求先使用e2fsck-因此:
e2fsck -f -y xxx.img
(不得安装映像!)
注意:这仅在映像属于单个分区的情况下才有效,如果它是具有多个分区的整个块设备,请参见上面的答案...
losetup --find --partscan xxx.img
将映像文件设置为循环设备。然后运行lsblk
以查找循环设备的分区。
resize2fs
仅适用于extN
类型分区。其他类型的分区将需要其他工具。
我也使用qemu-img尝试了一下,它就像一个魅力:
qemu-img resize test.img 2G
我们正在调整其大小test.img
以使其达到2G(2GB)。
为我工作完美。
df -h
显示原始大小。这怎么可能?
我在我的Ubuntu 16.10计算机上使用了gparted方法:
1)使用,将img文件映射到下一个可用的循环分区losetup
,如上述先前文章所述
2)检查 lsblk
图像文件映射到哪个循环驱动器,例如/dev/loop0
3)执行 sudo gparted /dev/loop0
4)适当缩小环路分区;请确保卸载这些分区。
5)执行fdisk /dev/loop0
,然后输入p
,这将向您显示各个分区的块大小和结束块号。
6)执行dd if=/dev/loop0 of=shrunk_image_file.img
,适用于该命令的选项bs=[BlockSize]
和count=[EndBlockNumberOfLastLoopPartition+1]
,你将有一个缩水,rightsized图像文件。