dd ทำงานเลยจุดสิ้นสุดของอุปกรณ์อินพุต

Aug 18 2020

ฉันกำลังพยายามใช้ddเพื่อโคลนฮาร์ดไดรฟ์ที่ฉันซ่อม ฉันกำลังพยายามddคัดลอกข้อมูลออกจากไดรฟ์เป็นชิ้น 10GB แต่กำลังถ่ายโอนข้อมูลมากกว่าที่ไดรฟ์ควรมี ไดรฟ์เองทำหน้าที่และสามารถติดตั้งพาร์ติชันบนไดรฟ์ได้

เมื่อใช้df -hฉันได้ขนาดของไดรฟ์เป็น 1,000204886016 ไบต์ (ไดรฟ์ 1TB)

ตอนแรกฉันพยายาม:

sudo dd if=/dev/sdb of=/dev/sdd status=progress

อย่างไรก็ตามสิ่งนี้ทำให้การรวบรวมข้อมูลช้าลงหลังจากประมาณ 300GB และในที่สุดก็ล้มเหลวเนื่องจากข้อผิดพลาดในการอ่าน ฉันตัดสินใจลองคัดลอกเป็นชิ้น 10GB ฉันคำนวณว่าการอ่าน 10GB ด้วยขนาดบล็อก 128kByte ต้องคัดลอก 78125 บล็อก

ในการทำสิ่งนี้ฉันใช้:

sudo dd if=/dev/sdb of=/dev/sdd bs=128k count=78125 status=progress oflag=seek_bytes seek=n

ddได้รับรายงานว่ามีการโอน 10240000000 ไบต์ในแต่ละครั้ง ในการคำนวณค่าการค้นหาสำหรับการวนซ้ำแต่ละครั้งฉันจะรวมไบต์ที่ถ่ายโอนและลบ 1GB เพื่อให้แน่ใจว่ามีการทับซ้อนกัน ลำดับผลลัพธ์คือ:

seek=0
seek=9240000000
seek=18480000000
seek=27720000000
seek=36960000000
...
seek=1071840000000

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

sudo dd if=/dev/sdb of=/dev/sdd bs=128k count=78125 status=progress oflag=seek_bytes seek=0
sudo dd if=/dev/sdb of=/dev/sdd bs=128k count=78125 status=progress oflag=seek_bytes seek=9240000000
sudo dd if=/dev/sdb of=/dev/sdd bs=128k count=78125 status=progress oflag=seek_bytes seek=18480000000
sudo dd if=/dev/sdb of=/dev/sdd bs=128k count=78125 status=progress oflag=seek_bytes seek=27720000000
sudo dd if=/dev/sdb of=/dev/sdd bs=128k count=78125 status=progress oflag=seek_bytes seek=36960000000
    ...
sudo dd if=/dev/sdb of=/dev/sdd bs=128k status=progress oflag=seek_bytes seek=1071840000000

มันควรจะวิ่งไปไกลจากจุดสิ้นสุดของไดรฟ์โดยการวนซ้ำครั้งสุดท้ายอย่างไรก็ตามมันก็ยังคงดำเนินต่อไป โคลนติดตั้ง แต่ข้อมูลที่เสียหายและขาดหายไปอย่างชัดเจน

  1. มีสิ่งผิดปกติกับคณิตศาสตร์ของฉันหรือข้อโต้แย้งที่ผมใช้กับdd?
  2. มีวิธีที่ดีกว่าสำหรับฉันในการเขียนคำสั่ง 'dd' เพื่อดึงข้อมูลออกเป็นชิ้น ๆ 10GB หรือไม่

คำตอบ

3 thatotherguy Aug 18 2020 at 02:31

ปัญหาคือคุณสมมติว่าseekรับค่าไบต์เมื่อในความเป็นจริงต้องใช้จำนวนบล็อก คุณควรจะใช้seek=0, 78125, 156250ฯลฯ

อย่างไรก็ตามคุณสามารถทำให้มันง่ายขึ้นได้มากโดยการกำจัดdd:

split -b 10G < /dev/sdd
3 roaima Aug 18 2020 at 06:36

ฉันพยายามใช้ dd เพื่อโคลนฮาร์ดไดรฟ์ที่ฉันซ่อม

อย่า.

ใช้ddrescueแทนซึ่งทำงานได้ดีกับบล็อกที่อ่านไม่ได้และข้อผิดพลาดของสื่ออื่น ๆ

2 alphasierra Aug 21 2020 at 03:06

ฉันค้นพบสาเหตุที่การแก้ปัญหาของฉันล้มเหลวคือความเข้าใจผิดว่าการตั้งค่าสถานะการค้นหาทำอะไร มันเป็นเพียงการเปลี่ยนตำแหน่งการเขียนบนไดรฟ์เอาท์พุท ดังนั้นสคริปต์ก็แค่คัดลอก 10GB แรกซ้ำแล้วซ้ำอีกไปยังเอาต์พุต มันจะไม่ถึงจุดสิ้นสุดของอุปกรณ์

ในการเปลี่ยนอินพุตจำเป็นต้องใช้ค่าสถานะการข้ามด้วย:

sudo dd if=/dev/sdb of=/dev/sdd bs=128k count=78125 status=progress skip=n seek=n

การตั้งค่าoflag=seek_bytesและiflag=skip_bytesจะช่วยให้การคำนวณเป็นไบต์เมื่อเทียบกับบล็อก

อย่างไรก็ตามตัวเลือกที่นำเสนอโดยroaima (ใช้ ddrescue) และตัวเลือกอื่น ๆ ( split -b 10G < /dev/sdd) เป็นวิธีที่ดีกว่าในการกู้คืนไดรฟ์ที่เสียหายและทำการโอนแบบแบ่งกลุ่มตามลำดับ