Perché il piping di `tar` in` dd` non si ferma finché il disco non è pieno?


18

Ho un archivio tar di una singola immagine del disco. L'immagine all'interno di questo file tar ha una dimensione di circa 4 GB. Inoltro l'output di tar xfin ddper scrivere l'immagine del disco su una scheda SD. Il discdump non si ferma mai fino a quando la scheda non è piena. Ecco la mia sessione di 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

Perché? Dovrebbe fermarsi dopo che hit ha scritto l'immagine da 4 GB sul carrello da 16 GB e non ha mai esaurito lo spazio!


Hai lo spazio su disco per provare a eseguirlo dde scriverlo su un altro file? tar zxf disk.img.tgz -O | dd status=progress conv=sync bs=1M of=/path/to/some/file/on/disk? In tal caso, ti procura una copia esatta del file originale?
Andy Dalton,

2
Perché hai conv=sync? Intendevi conv=fsyncforse usare ?
Ralph Rönnquist,

Sei sicuro che sia la dimensione reale del file? So che gzip ha solo 32 bit in cui memorizzare le dimensioni dei file, quindi sbaglia la dimensione dei file oltre i 4 GB. Non sono sicuro che tar abbia una limitazione simile.
David Conrad,

Risposte:


50

È perché stai sbagliando.

Stai usando, bs=1Mma la lettura da stdin, pipe, avrà letture più piccole. In effetti, secondo dd, non hai ottenuto una sola lettura completa.

E poi hai conv=syncquali complementi letture incomplete con zero.

0+15281 records in
15280+0 records out

ddha ricevuto 0 letture complete e 15281 incomplete e ha scritto 15280 blocchi completi (conv = sync zero riempito). Quindi l'output è molto più grande dell'input, fino a quando non avrai più spazio.

   sync   pad  every  input  block  with  NULs to ibs-size; when used with
          block or unblock, pad with spaces rather than NULs

Per risolvere questo, è possibile rimuovere conv=synce aggiungere iflag=fullblock.


Per illustrare, si consideri yesche per impostazione predefinita viene emesso "y \ ny \ ny \ n" infinito.

$ yes
y
y
y
^C
$ yes | hexdump -C
00000000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*

Con dd bs=1M conv=syncsembra così:

$ yes | dd bs=1M conv=sync | hexdump -C
00000000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*
0001e000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00100000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*
00112000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*

Quindi ottiene un blocco incompleto di "y \ ny \ ny \ n" (0x00000 - 0x1e000, 122880 byte) quindi scrive i restanti 1M come zero (0x01e000 - 0x100000, 925696 byte). Nella maggior parte dei casi, non vuoi che ciò accada. Il risultato è comunque casuale poiché non hai alcun controllo reale su quanto ogni lettura sarebbe incompleta. Come qui la seconda lettura non è più 122880 byte ma 73728 byte.

dd conv=syncè raramente utile e anche nei casi in cui sarebbe il benvenuto, come scrivere zero quando si ottengono errori di lettura, le cose andranno terribilmente male.


In questo caso, l'esecuzione del ddcomando in strace(presupponendo che Linux) avrebbe mostrato che ogni breve lettura dalla pipe era seguita da una scrittura completa da 1 MB.
Andrew Henle,

2
@AndrewHenle non ha nemmeno bisogno di una battuta per questo, basta guardare l'output. Aggiunta un'illustrazione
frostschutz,

Ciò illustra anche perché il ddcomando è sostanzialmente rotto e inutilizzabile. E 'specificato per operare nei singoli reads e writes, ma le operazioni sono specificate in modo tale che essi possono sempre produrre breve legge o scrive, e non è un errore. Di conseguenza, il comportamento di dddipende da un comportamento non specificato.
R ..

Grazie per la risposta molto educativa. Come qualcun altro ha suggerito che ero un asino e ho confuso le molte opzioni dd, ma mi ha portato a imparare qualcosa da te. Ciò di cui non sono ancora del tutto sicuro è se e quando ddsarebbe terminato. Presumo che lo avrebbe fatto, ma dato che stava scrivendo 1 parte di dati effettivi e 9 parti di zero, si sarebbe fermato dopo aver scritto circa 40G. È corretto?
con-f-use

@R .., questa funzione è molto utile con i driver di dispositivo che si preoccupano della dimensione del blocco di letture e scritture. Ricordo di aver usato alcune unità nastro a cui importava. Anche se in questo caso, ovviamente, non è necessario, si potrebbe semplicemente reindirizzare direttamente sul disco (non ottenendo un rapporto sui progressi in tempo reale)
ilkkachu
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.