สร้างข้อมูลแบบสุ่มด้วย dd และรับ“ คำเตือนการอ่านบางส่วน” ข้อมูลหลังจากการเตือนตอนนี้สุ่มจริงๆหรือไม่?


16

ฉันจะสร้างไฟล์ 1TB dd if=/dev/urandom of=file bs=1M count=1000000กับข้อมูลแบบสุ่มด้วย ตอนนี้ฉันตรวจสอบkill -SIGUSR1 <PID>ความคืบหน้าและรับสิ่งต่อไปนี้:

691581+0 Datensätze ein
691580+0 Datensätze aus
725174190080 Bytes (725 GB) kopiert, 86256,9 s, 8,4 MB/s
800950+1 Datensätze ein
800950+0 Datensätze aus
839856947200 Bytes (840 GB) kopiert, 99429,5 s, 8,4 MB/s
dd: warning: partial read (809620 bytes); suggest iflag=fullblock
803432+1 Datensätze ein
803431+1 Datensätze aus
842459273876 Bytes (842 GB) kopiert, 99791,3 s, 8,4 MB/s

ฉันไม่สามารถตีความคำเตือนได้ มันพูดว่าอะไร? ไฟล์ของฉันเป็นแบบสุ่มจริง ๆ หลังจากได้รับคำเตือนหรือมีปัญหาหรือไม่? +0 หรือ +1 ใน800950+1 Datensätze einและ800950+0 Datensätze ausหมายถึงอะไร หลังจากคำเตือนมันคือ +1 มันเป็นข้อผิดพลาดหรือไม่?


นี่จะตอบได้ง่ายกว่าถ้าคุณสามารถแปลข้อความเป็นภาษาอังกฤษได้ นอกจากนี้กำหนด "สุ่มจริงๆ" คุณต้องการการสุ่มในระดับใดคุณจะใช้มันเพื่ออะไร
terdon

ในการรับข้อความภาษาอังกฤษใช้LC_ALL=Cหน้าคำสั่งเช่นLC_ALL=C dd if=...
Volker Siegel

คำตอบ:


38

สรุป: ddเป็นเครื่องมือที่บ้าๆบอ ๆ ซึ่งยากต่อการใช้งานอย่างถูกต้อง อย่าใช้มันแม้จะมีบทเรียนมากมายที่บอกคุณ ddมีกลิ่นอาย "ถนนยูนิกซ์" ติดอยู่กับมัน - แต่ถ้าคุณเข้าใจอย่างแท้จริงว่าคุณกำลังทำอะไรอยู่คุณจะรู้ว่าคุณไม่ควรแตะเสา 10 ฟุต

ddทำให้การเรียกครั้งเดียวไปยังการreadเรียกระบบต่อบล็อก (กำหนดโดยค่าของbs) ไม่รับประกันว่าการreadเรียกของระบบจะส่งคืนข้อมูลมากเท่ากับขนาดบัฟเฟอร์ที่ระบุ สิ่งนี้มีแนวโน้มที่จะทำงานกับไฟล์และอุปกรณ์บล็อกปกติ แต่ไม่ใช่สำหรับไปป์และอุปกรณ์ตัวอักษรบางตัว ดูที่เมื่อใดจึงเหมาะสำหรับการคัดลอกข้อมูล (หรือเมื่อมีการอ่าน () และเขียน () บางส่วน)สำหรับข้อมูลเพิ่มเติม หากการreadเรียกระบบส่งคืนบล็อกเต็มน้อยกว่าหนึ่งบล็อกให้ddโอนบล็อกบางส่วน มันยังคงคัดลอกจำนวนบล็อกที่ระบุดังนั้นจำนวนไบต์ที่ถ่ายโอนทั้งหมดจะน้อยกว่าที่ร้องขอ

คำเตือนเกี่ยวกับ“ การอ่านบางส่วน” จะบอกคุณตรงนี้: หนึ่งในการอ่านนั้นเป็นบางส่วนดังนั้นจึงddโอนบล็อกที่ไม่สมบูรณ์ ในการนับบล็อก+1หมายถึงการอ่านบล็อกหนึ่งส่วน เนื่องจากจำนวนเอาต์พุตคือ+0บล็อกทั้งหมดจึงถูกเขียนเป็นอ่าน

นี้ไม่ได้ส่งผลกระทบต่อการสุ่มของข้อมูล: ไบต์ทั้งหมดที่เขียนออกมาเป็นไบต์ว่ามันอ่านจากdd /dev/urandomแต่คุณมีไบต์น้อยกว่าที่คาดไว้

Linux /dev/urandomรองรับการร้องขอขนาดใหญ่ตามอำเภอใจ (ที่มา: extract_entropy_userในdrivers/char/random.c) ดังนั้นddโดยปกติแล้วจะปลอดภัยเมื่ออ่านจากมัน อย่างไรก็ตามการอ่านข้อมูลจำนวนมากต้องใช้เวลา หากกระบวนการได้รับสัญญาณการreadเรียกของระบบจะส่งกลับก่อนเติมบัฟเฟอร์เอาต์พุต นี่เป็นพฤติกรรมปกติและแอปพลิเคชันควรจะเรียกreadเป็นลูป ddไม่ได้ทำสิ่งนี้ด้วยเหตุผลทางประวัติศาสตร์ ( ddต้นกำเนิดมืดมัว แต่ดูเหมือนว่าจะเป็นเครื่องมือในการเข้าถึงเทปซึ่งมีข้อกำหนดแปลก ๆ และไม่เคยถูกดัดแปลงให้เป็นเครื่องมืออเนกประสงค์ทั่วไป) เมื่อคุณตรวจสอบความคืบหน้าสิ่งนี้จะส่งddสัญญาณที่ขัดจังหวะการอ่าน คุณมีทางเลือกระหว่างการรู้จำนวนไบต์ddจะคัดลอกทั้งหมด (ตรวจสอบให้แน่ใจว่าจะไม่ขัดจังหวะ - ไม่มีการตรวจสอบความคืบหน้าไม่มีการหยุดชั่วคราว) หรือรู้ว่ามีกี่ไบต์ที่ddคัดลอกมาแล้วซึ่งในกรณีนี้คุณไม่สามารถรู้ได้ว่าจะคัดลอกจำนวนเท่าใด

เวอร์ชันของddใน GNU coreutils (ตามที่พบใน Linux ที่ไม่ได้ฝังตัวและบน Cygwin) มีการตั้งค่าสถานะfullblockซึ่งบอกddให้เรียกใช้readในลูป (และเหมือนกันสำหรับwrite) และจึงถ่ายโอนบล็อกเต็มเสมอ ข้อความแสดงข้อผิดพลาดแสดงให้เห็นว่าคุณใช้มัน คุณควรใช้มัน (ทั้งในอินพุตและแฟล็กเอาท์พุท) ยกเว้นในกรณีพิเศษมาก (ส่วนใหญ่เมื่อเข้าถึงเทป) - ถ้าคุณใช้ddเลยนั่นคือ: มักจะมีวิธีแก้ปัญหาที่ดีกว่า (ดูด้านล่าง)

dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000

อีกวิธีที่เป็นไปได้เพื่อให้แน่ใจว่าสิ่งที่ddจะทำคือการส่งขนาดบล็อก 1 จากนั้นคุณสามารถบอกได้ว่ามีกี่ไบต์ที่ถูกคัดลอกจากการนับจำนวนบล็อก แต่ฉันไม่แน่ใจว่าจะเกิดอะไรขึ้นถ้า a readถูกขัดจังหวะก่อนอ่านครั้งแรก ไบต์ (ซึ่งไม่น่าเป็นไปได้ในทางปฏิบัติ แต่สามารถเกิดขึ้นได้) อย่างไรก็ตามแม้ว่ามันจะทำงานได้ช้ามาก

คำแนะนำทั่วไปเกี่ยวกับการใช้ddมีที่ไม่ได้ใช้ ddแม้ว่าddโฆษณามักจะเป็นคำสั่งระดับต่ำในการเข้าถึงอุปกรณ์ แต่ในความเป็นจริงแล้วไม่มีสิ่งดังกล่าว: ความมหัศจรรย์ทั้งหมดที่เกิดขึ้นในไฟล์อุปกรณ์ ( /dev/…ส่วน) ddเป็นเพียงเครื่องมือธรรมดาที่มีศักยภาพสูงสำหรับการใช้งานในทางที่ผิด . ในกรณีส่วนใหญ่มีวิธีที่ง่ายและปลอดภัยกว่าในการทำสิ่งที่คุณต้องการอย่างน้อยใน Linux

ตัวอย่างเช่นในการอ่านจำนวนไบต์ที่จุดเริ่มต้นของไฟล์เพียงโทรhead:

head -c 1000000m </dev/urandom >file

ฉันทำมาตรฐานอย่างรวดเร็วในเครื่องของฉันและไม่ได้สังเกตเห็นความแตกต่างระหว่างการใด ๆที่มีขนาดใหญ่และบล็อกddhead

หากคุณต้องการที่จะข้ามไบต์บางที่จุดเริ่มต้นท่อtailลงไปhead:

dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output

หากคุณต้องการเห็นความคืบหน้าโทรlsofเพื่อดูไฟล์ชดเชย ใช้งานได้กับไฟล์ปกติเท่านั้น (ไฟล์เอาต์พุตในตัวอย่างของคุณ) ไม่ใช่อุปกรณ์ตัวอักษร

lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1

คุณสามารถโทรติดต่อpvเพื่อรับรายงานความคืบหน้า (ดีกว่าdd) ด้วยค่าใช้จ่ายของรายการเพิ่มเติมในไปป์ไลน์ (โดยคำนึงถึงประสิทธิภาพ


2
+1 นี่เป็นหนึ่งในโพสต์ที่มีการวิจัยที่ดีที่สุดที่ฉันได้อ่านบนเครือข่าย StackExchange ในเวลานาน มันกระชับ แต่มีรายละเอียดทั้งหมด (ประวัติศาสตร์และปัจจุบัน) เกี่ยวกับddคำสั่งที่ฉันไม่ได้รู้ว่าฉันจำเป็นต้องรู้ ขอบคุณ
Ossifrage ของจักรวาล

4
ฉันขอโทษ แต่ฉันไม่เห็นด้วยกับการยืนยันของคุณว่า dd เป็น "เครื่องมือบ้าๆบอ ๆ ที่ยากต่อการใช้อย่างถูกต้อง" และ "ไม่ใช้ dd" มันเป็นยูทิลิตี้ที่สมบูรณ์แบบเมื่อใช้อย่างถูกต้องโดยคนที่ใช้เวลาในการทำความเข้าใจ จริง ๆ แล้วชุดเครื่องมือทางนิติวิทยาศาสตร์ดิสก์เกือบทั้งหมดขึ้นอยู่กับ dd หรืออนุพันธ์เช่น dcfldd
fpmurphy

1
@ fpmurphy1 GNU ddสามารถใช้ได้อย่างปลอดภัยด้วยfullblockตัวเลือก แต่ถ้าคุณมี coreutils ของ GNU คุณไม่ต้องการddอะไรมาก “สัญญาซื้อขายล่วงหน้า” เช่นdcflddจะไม่ได้ ddพวกเขาจะไม่ต้องทนทุกข์ทรมานจากข้อบกพร่องของตนเพื่อให้คำตอบของฉันไม่ได้นำไปใช้กับพวกเขา คนส่วนใหญ่ที่ใช้ddไม่ได้มีเวลาพอที่จะเข้าใจ (ส่วนใหญ่พวกเขาใช้เวลาในการคิดว่าพวกเขาเข้าใจ) และวิธีที่พวกเขาใช้นำไปสู่การสูญเสียข้อมูล
Gilles 'ดังนั้นหยุดความชั่วร้าย'

1
@Gilles ดังนั้นเราไม่ควรใช้ "echo" b / c ของศักยภาพในการใช้ผิดวัตถุประสงค์ (sudo echo hello world> / dev / sda)?
whitey04

2
@ whitey04 ฉันไม่แนะนำให้จัดการกับถังไนโตรกลีเซอรีน ฉันไม่ได้บอกว่าคุณไม่ควรใช้แมทช์
Gilles 'หยุดความชั่วร้าย' ใน

9

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

ไม่มีปัญหากับความถูกต้องของข้อมูล แต่ปัญหาคือการddนับการอ่านบางส่วนเป็นบล็อกการอ่าน

หากคุณไม่ได้ใช้countตัวเลือกคำเตือนแทบจะไม่สำคัญเลยมันเป็นเพียงการพิจารณาประสิทธิภาพ แต่ด้วยcountคุณจะไม่ได้รับปริมาณข้อมูลที่คุณร้องขอ เนื่องจากการอ่านบางส่วนofจะมีขนาดเล็กกว่าcount*bsตอนท้าย

ดังนั้นเมื่อคุณใช้countเทคนิคคุณควรใช้iflag=fullblockเช่นกัน

+xควรจะเป็นจำนวนบล็อกบางส่วน


-3
< /dev/urandom \
dd ibs=4k obs=64k |
dd bs=64k count=16000000 >file

^ นั่นจะใช้งานได้ ข้อมูลที่ผิดอย่างอื่นมีที่นี่เป็นเท็จอย่างชัดแจ้ง ddบัฟเฟอร์มีความชัดเจนดังนั้นการบัฟเฟอร์อินพุตเพื่อนับเหตุการณ์ที่คุณต้องการบัฟเฟอร์อย่างชัดเจน นั้นคือทั้งหมด. อย่าซื้อความอับอาย

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