Eu tenho um arquivo tar de uma única imagem de disco. A imagem dentro deste arquivo tar tem cerca de 4 GB de tamanho. Eu canalizo a saída tar xf
para dd
para gravar a imagem do disco em um cartão SD. O despejo de disco nunca para até que o cartão esteja cheio. Aqui está minha sessão 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ê? Ele deve parar após o hit gravar a imagem de 4 GB no carrinho de 16 GB e nunca ficar sem espaço!
pipe
tar
dd
disk-image
confundir
fonte
fonte
dd
e gravá-lo em outro arquivo?tar zxf disk.img.tgz -O | dd status=progress conv=sync bs=1M of=/path/to/some/file/on/disk
? Em caso afirmativo, isso fornece uma cópia exata do arquivo original?conv=sync
? Você quis usarconv=fsync
talvez?Respostas:
É porque você está fazendo errado.
Você está usando,
bs=1M
mas a leitura de stdin, pipe, terá leituras menores. De fato, de acordo com o dd, você não obteve uma única leitura completa.E então você tem
conv=sync
quais complementos leituras incompletas com zeros.dd
recebeu 0 leituras completas e 15281 incompletas e escreveu 15280 blocos completos (conv = sincronização zero preenchida). Portanto, a saída é muito maior do que a entrada, até que você não tenha mais espaço.Para resolver isso, você pode remover
conv=sync
e adicionariflag=fullblock
.Para ilustrar, considere
yes
que, por padrão, exibe "y \ ny \ ny \ n" infinito.Com
dd bs=1M conv=sync
isso fica assim:Portanto, ele obtém um bloco incompleto de "y \ ny \ ny \ n" (0x00000 - 0x1e000, 122880 bytes) e grava o 1M restante como zeros (0x01e000 - 0x100000, 925696 bytes). Na maioria dos casos, você não deseja que isso aconteça. De qualquer forma, o resultado é aleatório, pois você não tem controle real sobre o quão incompleta cada leitura se tornaria. Como aqui, a segunda leitura não é mais 122880 bytes, mas 73728 bytes.
dd conv=sync
raramente é útil e, mesmo nos casos em que seria bem-vindo, como escrever zeros quando você obtém erros de leitura, as coisas vão dar terrivelmente errado.fonte
dd
comando emstrace
(assumindo Linux) mostraria que cada leitura curta do canal era seguida por uma gravação completa de 1 MB.dd
comando é fundamentalmente quebrado e inutilizável. Ele é especificado para operar emread
s e s individuaiswrite
, mas essas operações são especificadas para que possam sempre produzir leituras ou gravações curtas, e isso não é um erro. Como conseqüência, o comportamento dedd
depende de um comportamento não especificado.dd
, mas isso me levou a aprender algo com você. O que ainda não tenho certeza absoluta é se e quandodd
terminariam. Eu suponho que sim, mas como na verdade ele estava gravando 1 parte de dados reais e 9 partes de zeros, teria parado depois de escrever sobre 40G. Isso está correto?