สรุป: 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) ด้วยค่าใช้จ่ายของรายการเพิ่มเติมในไปป์ไลน์ (โดยคำนึงถึงประสิทธิภาพ