Как преобразовать образ диска Linux в разреженный файл?

12

У меня есть куча образов дисков, созданных с помощью 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нет на смонтированном образе диска.

эндолиты
источник
2
Запись нулей в файл не создаст разреженный файл. Это другая концепция. Когда вы ищете / читаете разреженный файл, когда ОС обнаруживает, что блока данных на самом деле нет (список блоков пуст для данных в этой области), она (ОС) автоматически волшебным образом заполняет буфер чтения нулевыми байтами.
Хотей
Примечание: sudo cat /dev/zero > zero.fileне работает, потому что ваш bash (работает как вы, а не root) выполняет перенаправление перед выполнением sudoкоманды. См. Unix.stackexchange.com/questions/1416/…
Фриц

Ответы:

19

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

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

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 --sparse=always original sparsefile

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

Михи
источник
1
Согласно Википедии, написание нулей с помощью dd создаст разреженный файл. Можете ли вы объяснить, что значит «искать»?
эндолит
1
А как насчет кота? На странице руководства нет ничего о разреженных файлах, поэтому я полагаю, что cat /dev/zero > zero.fileвсе в порядке, чтобы заполнить пустое пространство нулями?
Людвиг Вайнцерль
2
@endolith: обновил мой ответ, чтобы прояснить, какая разница использовать ddдля записи нулей или для поиска.
Михи
2
@Ludwig Weinzierl: Да, эта catкоманда заполнит весь ваш диск (или хотя бы сумму, не зарезервированную для root или квотами) "реальными" нулями и не создаст разреженных файлов.
Михи
1
@endolith тебе понадобится дополнительное место, да. но поскольку вы можете сжать архив, вам понадобится только место для исходного файла и сжатой версии разреженного файла.
Михи
12

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

fallocate -v --dig-holes {file_name}

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

Onlyjob
источник
1
По какой-то причине я fallocate --dig-holesполучил файл 103GiB из оригинала 299GiB, а 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

Лам Дас
источник
по состоянию на 2012 git.savannah.gnu.org/cgit/coreutils.git/commit/...
эндолиты
1
Да, этот вариант не с того момента, когда ОП спросил. Это было больше «оставить хлебную крошку для других искателей» ... :-)
Лам Дас
1
в зависимости от типа файловой системы zerofreeможет быть быстрее, чем монтировать и записывать нули в файловую систему, и уменьшать размер образа диска, если он уже содержит много нулей.
Михи
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

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

Grumbel
источник
1
К сожалению, изображения, созданные с помощью partimage, не могут быть смонтированы без повторного их расширения, что делает их пригодными только для архивных целей.
Перкинс
0

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

эндолиты
источник
-2

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

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

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

Хотей
источник
Интересно, но я заметил, что нет опровержения того, что я написал. Если это точно, но бесполезно, это не повод для отрицания. Если это не точно и не полезно, тогда это заслуживает этого.
Хотей
В другом месте я вижу, что у ОП был вопрос, связанный с монтированием сжатых изображений. Я предполагаю, что это продолжение этой темы. Зная, что теперь я понимаю, почему мое предложение о сжатии не было принято. Простая программа на C все еще является простым способом создания разреженных файлов. НО - позволит (не указанная) ОС разрешить монтирование разреженного ISO. Столь же требователен как монтировщик Ubuntu ISO, я не уверен на 100%, что это тоже сработает ... но в любом случае, удачи.
Хотей
4
зачем изобретать велосипед? cp --sparse=alwaysотлично работает
Михи
@mihi: Это хорошая идея. Я не знал о разреженной опции, так как она недоступна в версиях BSD ( freebsd.org/cgi/… ), и у меня никогда не было необходимости просматривать справочную страницу Linux для cp (до сегодняшнего дня).
Хотей
Один из способов получить сжатые образы и смонтировать их - просто сохранить их в файловой системе, которая поддерживает собственное сжатие. Делает восстановление данных ужасным, если у вас сбой диска, но для этого нужны резервные копии, верно?
Перкинс