Mam archiwum tar jednego obrazu dysku. Obraz w tym pliku tar ma rozmiar około 4 GB. Przesyłam dane wyjściowe do tar xf
w dd
celu zapisania obrazu dysku na karcie SD. Zrzut dysku nigdy się nie zatrzymuje, dopóki karta nie jest pełna. Oto moja sesja powłoki:
$ 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
Dlaczego? Powinno się zatrzymać po tym, jak hit zapisał obraz 4 GB do koszyka 16 GB i nigdy nie zabraknie miejsca!
pipe
tar
dd
disk-image
dezorientować
źródło
źródło
dd
i zapisać w innym pliku?tar zxf disk.img.tgz -O | dd status=progress conv=sync bs=1M of=/path/to/some/file/on/disk
? Jeśli tak, to czy otrzymujesz dokładną kopię oryginalnego pliku?conv=sync
? Czy chciałeś użyćconv=fsync
?Odpowiedzi:
To dlatego, że robisz to źle.
Używasz,
bs=1M
ale czytanie ze standardowego, potoku będzie miało mniejsze odczyty. W rzeczywistości, według dd, nie dostałeś ani jednego pełnego odczytu.A potem masz,
conv=sync
który uzupełnia niekompletne odczyty zerami.dd
otrzymał 0 pełnych i 15281 niepełnych odczytów i napisał 15280 pełnych bloków (conv = synchronizacja wypełniona zerem). Wyjście jest więc znacznie większe niż wejście, dopóki nie zostanie wolne miejsce.Aby rozwiązać ten problem, możesz usunąć
conv=sync
i dodaćiflag=fullblock
.Aby to zilustrować, zastanów się
yes
, która domyślnie wyrzuca nieskończone „y \ ny \ ny \ n”.Z
dd bs=1M conv=sync
wygląda to tak:Otrzymuje więc niekompletny blok „y \ ny \ ny \ n” (0x00000 - 0x1e000, 122880 bajtów), a następnie zapisuje pozostały 1M jako zera (0x01e000 - 0x100000, 925696 bajtów). W większości przypadków nie chcesz, aby tak się stało. Wynik jest w każdym razie losowy, ponieważ nie masz rzeczywistej kontroli nad tym, jak niekompletny byłby każdy odczyt. Tak jak tutaj, drugi odczyt to już nie 122880 bajtów, ale 73728 bajtów.
dd conv=sync
jest rzadko przydatny i nawet w przypadkach, w których byłoby to mile widziane, np. pisanie zer, gdy wystąpią błędy odczytu, wszystko pójdzie z tym okropnie źle.źródło
dd
polecenia podstrace
(zakładając, że Linux) pokazałoby, że po każdym krótkim odczycie z potoku następuje pełny zapis 1 MB.dd
polecenie jest zasadniczo złamane i nie nadaje się do użytku. Jest dostosowane do pracy w poszczególnychread
S iwrite
S, ale operacje te są określone tak, że zawsze mogą produkować krótkie odczytuje lub zapisuje, i to nie jest błąd. W konsekwencji zachowaniedd
zależy od nieokreślonego zachowania.dd
, ale doprowadziło mnie to do nauczenia się czegoś od ciebie. Nadal nie jestem całkowicie pewien, czy i kiedydd
by się skończyło . Zakładam, że tak, ale ponieważ faktycznie zapisywał 1 część rzeczywistych danych i 9 części zer, przestałby działać po zapisaniu około 40G. Czy to jest poprawne?