¿Cómo convierto una imagen de disco de Linux en un archivo disperso?

12

Tengo un montón de imágenes de disco, hechas con ddrescue, en una partición EXT, y quiero reducir su tamaño sin perder datos, sin dejar de ser montable.

¿Cómo puedo llenar el espacio vacío en el sistema de archivos de la imagen con ceros y luego convertir el archivo en un archivo disperso para que este espacio vacío no se almacene en el disco?

Por ejemplo:

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

Sin embargo, esto en realidad solo tiene 50G de datos reales, por lo que la segunda medición debería ser mucho más pequeña.

Esto supuestamente llenará el espacio vacío con ceros:

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

Pero si los archivos dispersos se manejan de manera transparente , en realidad podría crear un archivo disperso sin escribir nada en el disco virtual, irónicamente evitando que convierta la imagen del disco virtual en un archivo disperso. :) ¿Lo hace?

Nota: Por alguna razón, sudo dd if=/dev/zero of=./zero.filefunciona cuando catno funciona en una imagen de disco montada.

endolito
fuente
2
Escribir ceros en un archivo no creará un archivo disperso. Es un concepto diferente. A medida que busca / lee un archivo disperso cuando el sistema operativo descubre que el bloque de datos no está realmente allí (la lista de bloques está vacía para los datos en esa región), este (el sistema operativo) llena automáticamente el búfer de lectura con cero bytes.
hotei
Nota: sudo cat /dev/zero > zero.fileno funciona porque su bash (que se ejecuta como usted, no root) realiza la redirección antes de ejecutar el sudocomando. Ver unix.stackexchange.com/questions/1416/…
Fritz

Respuestas:

19

En primer lugar, los archivos dispersos solo se manejan de forma transparente si busca, no si escribe ceros.

Para que quede más claro, el ejemplo de Wikipedia

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

no no escribir los ceros, se abrirá el archivo de salida, busque (saltar) 5 MB y luego escribir cero ceros (es decir, nada en absoluto). Este comando ( no de Wikipedia)

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

¡escribirá 5MB de ceros y no creará un archivo disperso!

Como consecuencia, un archivo que ya no es escaso no se convertirá mágicamente en escaso más adelante.

En segundo lugar, para hacer un archivo con muchos ceros ralos, usted tiene que cp se

cp --sparse=always original sparsefile

o también puede usar la opción --sparse de tar 's o rsync ' s.

mihi
fuente
1
Según Wikipedia, escribir ceros con dd creará un archivo disperso. ¿Puedes explicar qué significa "buscar"?
endolito el
1
¿Qué hay de gato entonces? No hay nada en la página del manual acerca de los archivos dispersos, así que supongo que cat /dev/zero > zero.fileestá perfectamente bien llenar el espacio vacío con ceros.
Ludwig Weinzierl
2
@endolith: Actualicé mi respuesta para dejar en claro cuál es la diferencia ddpara escribir ceros o para buscar.
mihi
2
@Ludwig Weinzierl: Sí, ese catcomando llenará todo su disco (o al menos la cantidad no reservada para root o por cuotas) con ceros "reales", y no creará archivos dispersos.
mihi
1
@endolith necesitarás espacio extra, sí. pero como puede comprimir el tarball, solo necesitará espacio para el archivo original y una versión comprimida del archivo disperso.
mihi
12

Quizás la forma más fácil de esparcir un archivo en su lugar sería usar la fallocateutilidad de la siguiente manera:

fallocate -v --dig-holes {file_name}

Fallocate (1) es proporcionado por el paquete util-linux en Debian .

Solo trabajo
fuente
1
Por alguna razón, fallocate --dig-holesresultó en un archivo 103GiB del original 299GiB, mientras que cp --sparse=alwaysme dio 93GiB, todos con la misma suma SHA1 (tamaños verificados a través de du -B1Gvs du --apparent-size -B1G). Entonces fallocateparece dar resultados inferiores.
Ruslan
3

Editando mi respuesta para completar:

  1. Globo vacío FS espacio con ceros (ADVERTENCIA: esto cambia su imagen de disco):

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

Supongamos que da / dev / loop1 como el disco y solo hay una partición, de lo contrario, debemos repetir esto para cada partición con FS montable (ignorar la partición de intercambio, etc.).

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

Deja que termine al fracaso con ENOSPC.

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

  1. Copiar en una imagen dispersa:

'dd' tiene una opción para convertir un archivo con ceros a un archivo disperso:

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

Lam Das
fuente
1
Sí, esta opción no es desde el momento en que OP preguntó. Esto fue más de "dejar una miga de pan para otros buscadores" ... :-)
Lam Das
1
dependiendo del tipo de sistema de archivos, zerofreepuede ser más rápido que montar y escribir ceros en el sistema de archivos, y hacer que la imagen del disco crezca menos si ya contenía muchos ceros.
mihi
2

¿Quiere decir que su imagen creada con ddrescue es, digamos, 50 GB y en realidad algo mucho menos sería suficiente?

Si ese es el caso, ¿no podrías simplemente crear una nueva imagen con dd:

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

y luego crea un sistema de archivos en él:

mkfsofyourchoice some_image.img

luego simplemente monte la imagen y copie todo, desde la imagen anterior a la nueva. ¿Eso funcionaría para ti?

Janne Pikkarainen
fuente
2

PartImage puede crear imágenes de disco que solo almacenan los bloques usados ​​de un sistema de archivos, reduciendo drásticamente el espacio requerido al ignorar los bloques no utilizados. No creo que pueda montar directamente las imágenes resultantes, pero va:

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

Debe producir lo que desea (incluso podría ser posible pegar el último paso, no lo he intentado).

Grumbel
fuente
1
Desafortunadamente, las imágenes creadas por partimage no se pueden montar sin expandirlas nuevamente, lo que las hace adecuadas solo para fines de archivo.
Perkins
0

Ahora hay una herramienta llamada virt-sparsify que hará esto. Llena el espacio vacío con ceros y luego copia la imagen en un archivo disperso. Sin embargo, requiere instalar muchas dependencias.

endolito
fuente
-2

Sospecho que necesitará un programa personalizado escrito con esa especificación si eso es REALMENTE lo que desea hacer. Pero es...?

Si realmente tiene muchas áreas de cero, cualquier buena herramienta de compresión lo reducirá significativamente. Y tratar de escribir archivos dispersos no funcionará en todos los casos. Si recuerdo correctamente, incluso los archivos dispersos ocupan un mínimo de 1 bloque de almacenamiento de salida donde el bloque de entrada contiene CUALQUIER bit que no sea cero. Por ejemplo, supongamos que tenía un archivo que tenía un promedio de incluso 1 bit distinto de cero por bloque de 512 bytes, no se puede escribir "escasamente". Por cierto, no perderá datos si comprime el archivo con zip, bzip, bzip2 o p7zip. No son como compresión mpeg o jpeg con pérdida.

Por otro lado, si necesita realizar lecturas de búsqueda aleatoria en el archivo, la compresión podría ser más problemática de lo que vale y volverá a la escritura dispersa. Un programador competente de C o C ++ debería poder escribir algo así en una hora o menos.

hotei
fuente
Interesante: un voto negativo aún noto que no hay refutación de lo que escribí. Si es exacto pero inútil, esa no es razón para rechazarlo. Si no es preciso y no es útil, entonces lo merece.
hotei
Veo en otra parte que el OP tenía una pregunta relacionada con el montaje de imágenes comprimidas. Supongo que esto es una continuación de ese hilo. Sabiendo que ahora puedo ver por qué mi sugerencia de compresión no fue aceptada. Un simple programa en C sigue siendo una manera fácil de crear archivos dispersos. PERO: el sistema operativo (no especificado) le permitirá montar un ISO escaso. Tan exigente como el montador ISO de Ubuntu es que tampoco estoy 100% seguro de que vaya a funcionar ... pero la mejor de las suertes en cualquier caso.
hotei
44
¿Por qué reinventar la rueda? cp --sparse=alwaysfunciona bien
mihi
@mihi: Esa es una buena idea. No conocía la opción escasa, ya que no está disponible en sabores BSD ( freebsd.org/cgi/… ) y nunca tuve el requisito de mirar una página de manual de Linux para cp (hasta hoy).
hotei
Una forma de tener sus imágenes comprimidas y montarlas también es simplemente almacenarlas en un sistema de archivos que admita la compresión nativa. Hace que la recuperación de datos sea horrible si tiene un bloqueo de unidad, pero para eso están las copias de seguridad, ¿verdad?
Perkins