Saya memiliki arsip tar dari gambar disk tunggal. Gambar di dalam file tar ini berukuran sekitar 4GB. Saya menyalurkan output tar xf
ke dd
untuk menulis gambar disk ke kartu SD. Diskdump tidak pernah berhenti sampai kartu penuh. Inilah sesi shell saya:
$ 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
Mengapa? Seharusnya berhenti setelah hit telah menulis gambar 4GB ke keranjang 16GB dan tidak pernah kehabisan ruang!
pipe
tar
dd
disk-image
membingungkan
sumber
sumber
dd
dan menulisnya ke file lain?tar zxf disk.img.tgz -O | dd status=progress conv=sync bs=1M of=/path/to/some/file/on/disk
? Jika demikian, apakah itu memberi Anda salinan yang tepat dari file asli?conv=sync
? Apakah Anda bermaksud menggunakanconv=fsync
mungkin?Jawaban:
Itu karena Anda salah melakukannya.
Anda menggunakan
bs=1M
tetapi membaca dari stdin, pipa, akan memiliki bacaan yang lebih kecil. Bahkan, menurut dd, Anda tidak mendapatkan satu pun bacaan penuh.Dan kemudian Anda memiliki
conv=sync
komplemen yang tidak lengkap dibaca dengan nol.dd
menerima 0 penuh dan 15281 membaca tidak lengkap, dan menulis 15280 blok penuh (conv = sync zero filled). Jadi outputnya jauh lebih besar daripada input, sampai Anda tidak punya ruang tersisa.Untuk mengatasi ini, Anda dapat menghapus
conv=sync
dan menambahkaniflag=fullblock
.Sebagai ilustrasi, pertimbangkan
yes
, yang secara default memuntahkan infinite "y \ ny \ ny \ n".Dengan
dd bs=1M conv=sync
tampilannya seperti ini:Jadi ia mendapat blok tidak lengkap dari "y \ ny \ ny \ n" (0x00000 - 0x1e000, 122880 Bytes) kemudian menulis 1M sisanya sebagai nol (0x01e000 - 0x100000, 925696 Bytes). Dalam kebanyakan kasus, Anda tidak ingin ini terjadi. Bagaimanapun hasilnya adalah acak karena Anda tidak memiliki kontrol nyata atas bagaimana tidak lengkapnya setiap pembacaan. Seperti di sini bacaan kedua tidak lagi 122880 Bytes tetapi 73728 Bytes.
dd conv=sync
jarang berguna dan bahkan dalam kasus-kasus di mana itu akan diterima, seperti menulis nol ketika Anda mendapatkan kesalahan membaca, hal-hal buruk akan terjadi dengannya.sumber
dd
perintah di bawahstrace
(dengan asumsi Linux) akan menunjukkan bahwa setiap pembacaan singkat dari pipa diikuti oleh penulisan 1MB penuh.dd
perintah pada dasarnya rusak dan tidak dapat digunakan. Ini ditentukan untuk beroperasi di masing-masingread
danwrite
, tetapi operasi tersebut ditentukan sedemikian rupa sehingga mereka selalu dapat menghasilkan bacaan pendek atau tulis, dan itu bukan kesalahan. Akibatnya, perilakudd
tergantung pada perilaku yang tidak ditentukan.dd
, tetapi itu membuat saya belajar sesuatu dari Anda. Yang saya masih tidak yakin tentang adalah, jika dan kapandd
akan berakhir. Saya berasumsi, memang harus, tetapi karena sebenarnya menulis 1 bagian data aktual dan 9 bagian nol, itu akan berhenti setelah menulis sekitar 40G. Apakah itu benar?