如何将Linux磁盘映像转换为稀疏文件?


12

我在EXT分区上有一堆用ddrescue制作的磁盘映像,我想减小它们的大小而不丢失数据,同时仍然可以挂载。

我如何用零填充图像文件系统中的空白空间,然后将其转换为稀疏文件,从而使该空白空间实际上不存储在磁盘上?

例如:

> du -s --si --apparent-size Jimage.image 
120G Jimage.image
> du -s --si Jimage.image 
121G Jimage.image

但是,实际上它只有50G的真实数据,因此第二次测量应该小得多。

据说这将用零填充空白空间:

cat /dev/zero > zero.file
rm zero.file

但是,如果透明地处理稀疏文件,则它实际上可能会创建一个稀疏文件而不向虚拟磁盘写入任何内容,具有讽刺意味的是,这阻止了我将虚拟磁盘映像转换为稀疏文件本身。:) 可以?

注意:由于某些原因,sudo dd if=/dev/zero of=./zero.filecat不在已安装的磁盘映像上时可以使用。


2
将零写入文件不会创建稀疏文件。这是一个不同的概念。当您发现/读取稀疏文件时,如果操作系统发现数据块实际上不存在(该区域中的数据的阻止列表为空),它(操作系统)就会自动以零字节填充神奇的读取缓冲区。
hotei

注意:sudo cat /dev/zero > zero.file这不起作用,因为您的bash(以您的身份运行,而不是root用户)在执行sudo命令之前会进行重定向。参见unix.stackexchange.com/questions/1416/…–
Fritz

Answers:


19

首先,稀疏文件仅在您寻求时透明地处理,而不是在您写入零时透明地处理。

更清楚地说,来自维基百科的示例

dd if=/dev/zero of=sparse-file bs=1k count=0 seek=5120

没有写任何零,它会打开输出文件,寻求(跳过)5MB,然后写零(即什么都没有)。此命令(不是来自维基百科)

dd if=/dev/zero of=sparse-file bs=1k count=5120

将写入5MB的零,并且不会创建稀疏文件!

结果,已经非稀疏的文件将不会在以后神奇地变得稀疏。

其次,要与许多零稀疏的文件,你必须CP

cp --sparse=always original sparsefile

或者您也可以使用tarrsync的--sparse选项。


1
根据Wikipedia所述,用dd写入零将创建一个稀疏文件。您能解释“寻求”的含义吗?
endlith 2010年

1
那猫呢?手册页中没有关于稀疏文件的任何内容,因此我认为cat /dev/zero > zero.file用零填充空白完全可以吗?
路德维希·韦恩泽尔

2
@endolith:更新了我的答案,以清楚说明dd写零或查找所用的区别。
mihi 2010年

2
@Ludwig Weinzierl:是的,该cat命令将用“真实”零填充您的整个磁盘(或至少填充未为root或配额保留的磁盘),并且不创建稀疏文件。
mihi 2010年

1
@endolith,您将需要额外的空间,是的。但是由于您可以压缩压缩包,因此您仅需要空间来存放原始文件和稀疏文件的压缩版本。
mihi

12

稀疏放置文件的最简单方法可能是使用fallocate实用程序,如下所示:

fallocate -v --dig-holes {file_name}

fallocate(1)Debian上的util-linux软件包提供。


1
由于某种原因,fallocate --dig-holes从原来的299GiB生成了103GiB文件,而cp --sparse=always给了我93GiB —全部具有相同的SHA1和(通过du -B1Gvs 检查大小du --apparent-size -B1G)。因此fallocate似乎给出了次等的结果。
罗斯兰

3

编辑我的答案以确保完整性:

  1. 将空的FS空间用零气球增加(警告:这会更改磁盘映像):

losetup --partscan --find --show disk.img

假定它给/ dev / loop1作为磁盘,并且只有一个分区,否则我们需要为其中有可安装FS的每个分区重复此操作(忽略交换分区等)。

mkdir -p /mnt/tmp mount /dev/loop1p1 /mnt/tmp dd if=/dev/zero of=/mnt/tmp/tempfile

让它完成到ENOSPC失败。

/bin/rm -f /mnt/tmp/tempfile umount /mnt/tmp losetup -d /dev/loop1

  1. 复制到稀疏图片中:

'dd'具有将零的文件转换为稀疏文件的选项:

dd if=disk.img of=disk-sparse.img conv=sparse



1
是的,此选项不是从询问OP时开始的。这更多的是“把面包屑留给其他搜索者” ... :-)
Lam Das

1
取决于文件系统类型,它zerofree可能比将零装载和写入文件系统更快,并且如果磁盘映像已经包含很多零,则使磁盘映像增长得更少。
mihi

2

您是说您的ddrescue创建的映像是50 GB,实际上少得多就足够了吗?

如果是这种情况,您不能先用dd创建一个新映像:

dd if=/dev/zero of=some_image.img bs=1M count=20000

然后在其中创建一个文件系统:

mkfsofyourchoice some_image.img

然后只是挂载映像,然后将所有内容从旧映像复制到新映像?那对你有用吗?


2

PartImage可以创建仅存储文件系统已使用块的磁盘映像,从而通过忽略未使用的块来大大减少所需的空间。我认为您无法直接挂载生成的图像,但是要:

image -> partimage -> image -> cp --sparse=alway

应该产生您想要的(甚至可以坚持到最后一步,没有尝试过)。


1
不幸的是,由partimage创建的图像无法在不再次扩展的情况下安装,使其仅适用于存档目的。
珀金斯

0

现在有一个名为virt-sparsify的工具可以执行此操作。它用零填充空白空间,然后将图像复制到稀疏文件。但是,它需要安装很多依赖项。


-2

我怀疑如果您确实要这样做,那么您将需要一个按照该规范编写的自定义程序。但是...吗?

如果您实际上有很多全零区域,那么任何好的压缩工具都可以将其大大降低。并且尝试写稀疏文件并非在所有情况下都可行。如果我没记错的话,即使是稀疏文件也要占用至少1个输出存储块,其中输入块包含的任何非零位。例如,假设您有一个文件,平均每个512字节块甚至有1个非零位,则该文件不能“稀疏地”写入。顺便说一句,如果您使用zip,bzip,bzip2或p7zip压缩文件,则不会丢失数据。它们不像是有损的mpeg或jpeg压缩。

另一方面,如果您需要对文件进行随机寻道读取,则压缩可能比它值得的麻烦更多,并且您将返回稀疏写入。有能力的C或C ++程序员应该能够在一个小时或更短的时间内编写出类似的内容。


有趣的是-一票否决票,但我注意到对我写的内容没有反驳。如果它是准确的但无济于事,那就不是拒绝投票的理由。如果它不准确并且没有帮助,那么它确实值得。
hotei 2010年

我在其他地方看到OP遇到有关装入压缩映像的问题。我假设这是该线程的延续。知道我现在可以知道为什么我的压缩建议没有被接受。一个简单的C程序仍然是创建稀疏文件的简便方法。但是-(未指定)操作系统将允许您安装稀疏的ISO。与Ubuntu ISO挂载程序一样挑剔的我也不是100%肯定会正常工作...但是在任何情况下都好运。
hotei 2010年

4
为什么要重新发明轮子?cp --sparse=always做得很好

@mihi:好主意。我不知道稀疏选项,因为它在BSD风格中不可用(freebsd.org/cgi/…),而且我从来没有要求查看cp的Linux手册页(直到今天)。
hotei

拥有并压缩图像的一种方法就是将它们简单地存储在支持本机压缩的文件系统中。如果发生驱动器崩溃,则使数据恢复变得糟糕,但这就是备份的目的,对吧?
珀金斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.