Tengo un archivo tar de una sola imagen de disco. La imagen dentro de este archivo tar es de aproximadamente 4 GB de tamaño. Tubería que la salida de tar xf
al dd
escribir la imagen de disco en una tarjeta SD. El diskdump nunca se detiene hasta que la tarjeta está llena. Aquí está mi sesión de shell:
$ ls -l disk.img.tgz
-rw-r--r-- 1 confus confus 192M Okt 5 00:53
$ tar -tvf disk.img.tgz
-rw-r--r-- root/root 4294968320 2018-10-05 00:52 disk.img
$ lsblk -lb /dev/sdc
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sdc 8:32 1 16022241280 0 disk
$ tar zxf disk.img.tgz -O | sudo dd status=progress conv=sync bs=1M of=/dev/sdc
[sudo] password for user:
15992881152 bytes (16 GB, 15 GiB) copied, 212 s, 75,4 MB/s
dd: error writing '/dev/sdc': No space left on device
0+15281 records in
15280+0 records out
16022241280 bytes (16 GB, 15 GiB) copied, 217,67 s, 73,6 MB/s
¿Por qué? ¡Debería detenerse después de que Hit haya escrito la imagen de 4GB en el carrito de 16GB y nunca quedarse sin espacio!
pipe
tar
dd
disk-image
confundir
fuente
fuente
dd
y escribirlo en otro archivo?tar zxf disk.img.tgz -O | dd status=progress conv=sync bs=1M of=/path/to/some/file/on/disk
? Si es así, ¿te da una copia exacta del archivo original?conv=sync
? ¿Quisiste usarconv=fsync
tal vez?Respuestas:
Es porque lo estás haciendo mal.
Estás usando
bs=1M
pero leer desde stdin, pipe, tendrá lecturas más pequeñas. De hecho, según dd, no obtuvo una sola lectura completa.Y luego tienes
conv=sync
que complementa las lecturas incompletas con ceros.dd
recibió 0 lecturas completas y 15281 incompletas, y escribió 15280 bloques completos (conv = sincronización llena). Por lo tanto, la salida es mucho más grande que la entrada, hasta que no quede espacio.Para resolver esto, puede eliminar
conv=sync
y agregariflag=fullblock
.Para ilustrar, considere
yes
, que por defecto arroja infinito "y \ ny \ ny \ n".Con
dd bs=1M conv=sync
esto se ve así:Entonces obtiene un bloque incompleto de "y \ ny \ ny \ n" (0x00000 - 0x1e000, 122880 Bytes) y luego escribe el 1M restante como ceros (0x01e000 - 0x100000, 925696 Bytes). En la mayoría de los casos, no desea que esto suceda. El resultado es aleatorio de todos modos ya que no tienes control real sobre cuán incompleta resultaría ser cada lectura. Como aquí, la segunda lectura ya no es 122880 Bytes sino 73728 Bytes.
dd conv=sync
rara vez es útil e incluso en los casos en que sería bienvenido, como escribir ceros cuando recibes errores de lectura, las cosas saldrán terriblemente mal.fuente
dd
comando bajostrace
(suponiendo Linux) habría demostrado que cada lectura corta de la tubería fue seguida por una escritura completa de 1 MB.dd
comando está fundamentalmente roto e inutilizable. Se especifica para operar en individualesread
s ywrite
s, pero esas operaciones se especifican de forma que siempre se puede producir a corto lee o escribe, y no es un error. Como consecuencia, el comportamiento dedd
depende del comportamiento no especificado.dd
, pero me llevó a aprender algo de ti. De lo que todavía no estoy completamente seguro es, si y cuándodd
habría terminado. Supongo que sí, pero como en realidad estaba escribiendo 1 parte de datos reales y 9 partes de ceros, se habría detenido después de escribir aproximadamente 40G. ¿Es eso correcto?