ทำไมการส่งท่อ `tar 'ลงใน` dd' ไม่หยุดจนกว่าดิสก์จะเต็ม


18

ฉันมีไฟล์เก็บถาวร tar ของดิสก์อิมเมจเดียว ภาพภายในไฟล์ tar นี้มีขนาดประมาณ 4GB ฉันไพพ์เอาท์พุทของtar xfไปddยังเพื่อเขียนดิสก์อิมเมจไปยังการ์ด SD diskdump ไม่เคยหยุดจนกว่าการ์ดจะเต็ม นี่คือเซสชันเชลล์ของฉัน:

$ 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

ทำไม? มันควรจะหยุดหลังจากที่ตีได้เขียนภาพ 4GB ลงในรถเข็น 16GB และไม่เหลือพื้นที่ว่าง!


คุณมีพื้นที่ว่างของดิสก์เพื่อลองเรียกใช้ddและเขียนไปยังไฟล์อื่นหรือไม่? tar zxf disk.img.tgz -O | dd status=progress conv=sync bs=1M of=/path/to/some/file/on/disk? ถ้าเป็นเช่นนั้นคุณได้รับสำเนาที่แน่นอนของไฟล์ต้นฉบับหรือไม่?
Andy Dalton

2
ทำไมคุณมีconv=sync? คุณตั้งใจจะใช้conv=fsyncบางที
Ralph Rönnquist

คุณแน่ใจขนาดไฟล์ที่แท้จริงใช่ไหม ฉันรู้ว่า gzip มีเพียง 32 บิตในการจัดเก็บขนาดไฟล์ดังนั้นจึงทำให้ขนาดของไฟล์ผิดเกิน 4GB ฉันไม่แน่ใจว่า tar มีข้อ จำกัด ที่คล้ายกันหรือไม่
David Conrad

คำตอบ:


50

เป็นเพราะคุณทำผิด

คุณกำลังใช้bs=1Mแต่กำลังอ่านจาก stdin, pipe จะมีการอ่านน้อยลง ในความเป็นจริงตาม dd คุณไม่ได้รับการอ่านแบบเต็มเดียว

แล้วคุณมีการconv=syncเติมเต็มที่อ่านไม่สมบูรณ์ด้วยเลขศูนย์

0+15281 records in
15280+0 records out

ddได้รับ 0 แบบเต็มและการอ่านที่ไม่สมบูรณ์ 15281 ครั้งและเขียนบล็อกเต็ม 15280 บล็อก (conv = sync zero fill) ดังนั้นเอาต์พุตจะมีขนาดใหญ่กว่าอินพุตมากจนคุณไม่มีพื้นที่เหลือ

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

เพื่อแก้ปัญหานี้คุณสามารถลบและเพิ่มconv=synciflag=fullblock


หากต้องการแสดงตัวอย่างให้พิจารณาyesซึ่งตามค่าเริ่มต้นแล้วจะพ่น infinite "y \ ny \ ny \ n"

$ 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.|
*

ด้วยdd bs=1M conv=syncลักษณะเช่นนี้:

$ 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  |................|
*

ดังนั้นจึงได้รับบล็อกที่ไม่สมบูรณ์ของ "y \ ny \ ny \ n" (0x00000 - 0x1e000, 122880 Bytes) จากนั้นเขียน 1M ที่เหลือเป็นศูนย์ (0x01e000 - 0x100000, 925696 Bytes) ในกรณีส่วนใหญ่คุณไม่ต้องการให้สิ่งนี้เกิดขึ้น ผลที่ได้คือการสุ่มอย่างไรก็ตามคุณไม่สามารถควบคุมได้ว่าการอ่านแต่ละครั้งจะไม่สมบูรณ์ เช่นเดียวกับที่นี่การอ่านครั้งที่สองจะไม่เพิ่มอีก 12,2880 Bytes แต่ 73728 Bytes

dd conv=syncไม่ค่อยมีประโยชน์และแม้แต่ในกรณีที่ยินดีต้อนรับเช่นการเขียนเลขศูนย์เมื่อคุณได้รับข้อผิดพลาดในการอ่านสิ่งต่าง ๆ จะผิดปกติอย่างมาก


ในกรณีนี้การรันddคำสั่งภายใต้strace(สมมติว่า Linux) จะแสดงให้เห็นว่าแต่ละการอ่านสั้น ๆ จากไปป์นั้นตามด้วยการเขียนเต็ม 1MB
Andrew Henle

2
@ AndrewHenle ไม่ต้องการ strace สำหรับสิ่งนี้เพียงแค่ดูผลลัพธ์จะทำ เพิ่มภาพประกอบ
frostschutz

สิ่งนี้ยังแสดงให้เห็นว่าเหตุใดddคำสั่งจึงใช้งานไม่ได้และไม่สามารถใช้งานได้ มันถูกระบุให้ทำงานในแต่ละreads writeแต่การดำเนินการเหล่านั้นถูกระบุไว้เพื่อให้สามารถอ่านหรือเขียนสั้น ๆ ได้ตลอดเวลาและไม่ใช่ข้อผิดพลาด เป็นผลให้พฤติกรรมของddขึ้นอยู่กับพฤติกรรมที่ไม่ได้ระบุ
..

ขอบคุณสำหรับคำตอบทางการศึกษา อย่างที่คนอื่นแนะนำว่าฉันเป็นลาและผสมผสานตัวเลือกมากมายเข้าddด้วยกัน แต่มันทำให้ฉันเรียนรู้จากคุณ สิ่งที่ฉันยังไม่แน่ใจอย่างสมบูรณ์คือถ้าและเมื่อใดddจะยกเลิก ฉันคิดว่ามันน่าจะมี แต่เนื่องจากจริงแล้วมันเขียนข้อมูลจริง 1 ส่วนและเลขศูนย์ 9 ส่วนมันจะหยุดหลังจากเขียนประมาณ 40G ถูกต้องหรือไม่
con-f-use

@R .. คุณลักษณะนั้นมีประโยชน์อย่างมากกับไดรเวอร์อุปกรณ์ที่สนใจขนาดบล็อกของการอ่านและการเขียน ฉันจำได้ว่าใช้เทปไดรฟ์ที่ใส่ใจกับมัน แม้ว่าในกรณีนี้เห็นได้ชัดว่าไม่จำเป็น แต่เราสามารถเปลี่ยนเส้นทางไปยังดิสก์ได้โดยตรง (แต่ไม่ได้รับรายงานความคืบหน้าสด)
ilkkachu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.