11

У меня есть куча образов дисков, созданных с помощью ddrescue, в разделе EXT, и я хочу уменьшить их размер без потери данных, оставаясь при этом монтируемым.

Как я могу заполнить пустое пространство в файловой системе изображения нулями, а затем преобразовать файл в разреженный файл, чтобы это пустое пространство фактически не сохранялось на диске?

Например:

> 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.file работает, когда cat отсутствует на смонтированном образе диска.

7 ответов7

17

Во-первых, разреженные файлы обрабатываются прозрачно только при поиске, а не при записи нулей.

Чтобы было понятнее, пример из Википедии

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

не писать никаких нулей, он будет открыть выходной файл, искать (перепрыгнуть) 5МБЫ и затем записать нулевые нули (т.е. вообще ничего). Эта команда (не из Википедии)

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

напишет 5 МБ нулей и не создаст разреженный файл!

Как следствие, файл, который уже не является разреженным, волшебным образом не станет разреженным позже.

Во- вторых, чтобы сделать файл с большим количеством нулей разреженным, вы должны Cp его

cp --sparse=always original sparsefile

или вы можете использовать опцию tar или rsync --sparse.

8

Возможно, самый простой способ разбить файл на месте - это использовать утилиту fallocate следующим образом:

fallocate -v --dig-holes {file_name}

fallocate(1) предоставляется пакетом util-linux в Debian.

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

2

Вы имеете в виду, что ваш созданный ddrescue образ имеет, скажем, 50 ГБ, и в действительности чего-то гораздо меньшего будет достаточно?

Если это так, не могли бы вы сначала создать новое изображение с помощью 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

Должен производить то, что вы хотите (возможно, даже можно придерживаться последнего шага, не пытался).

0

Теперь есть инструмент под названием virt-sparsify, который сделает это. Он заполняет пустое пространство нулями, а затем копирует изображение в разреженный файл. Это требует установки множества зависимостей, хотя.

-2

Я подозреваю, что вам потребуется специальная программа, написанная для этой спецификации, если это действительно то, что вы хотите сделать. Но так ли это ...?

Если у вас на самом деле много областей с нулевым заполнением, то любой хороший инструмент сжатия значительно его сломает. И попытка записи разреженных файлов не будет работать во всех случаях. Если я правильно помню, даже разреженные файлы занимают минимум 1 блок памяти вывода, где блок ввода содержит ЛЮБЫЕ биты, которые не равны нулю. Например - скажем, у вас был файл, который имел в среднем даже 1 ненулевой бит на 512-байтовый блок - он не может быть записан "редко". Кстати, вы не потеряете данные, если сжимаете файл с помощью zip, bzip, bzip2 или p7zip. Они не похожи на сжатие mpeg или jpeg с потерями.

С другой стороны, если вам нужно выполнить произвольное чтение в файл, тогда сжатие может оказаться более трудным, чем оно того стоит, и вы вернетесь к разреженной записи. Компетентный программист на C или C++ должен уметь написать что-то подобное за час или меньше.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .