dd บนดิสก์ทั้งหมด แต่ไม่ต้องการส่วนที่ว่างเปล่า


33

ฉันมีดิสก์พูด / dev / sda

นี่คือ fdisk -l:

 Disk /dev/sda: 64.0 GB, 64023257088 bytes
255 heads, 63 sectors/track, 7783 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0000e4b5

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          27      209920   83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2              27         525     4000768    5  Extended
Partition 2 does not end on cylinder boundary.
/dev/sda5              27         353     2621440   83  Linux
/dev/sda6             353         405      416768   83  Linux
/dev/sda7             405         490      675840   83  Linux
/dev/sda8             490         525      282624   83  Linux

ฉันต้องสร้างภาพเพื่อจัดเก็บในไฟล์เซิร์ฟเวอร์ของเราเพื่อใช้ในการกระพริบอุปกรณ์อื่น ๆ ที่เรากำลังผลิตดังนั้นฉันต้องการเพียงพื้นที่ใช้งาน (ประมาณ 4GB เท่านั้น) ฉันต้องการเก็บ mbr ฯลฯ ... เนื่องจากอุปกรณ์นี้ควรบูตพร้อมทันทีที่การคัดลอกเสร็จสิ้น

ความคิดใด ๆ ก่อนหน้านี้ฉันเคยใช้dd if=/dev/sda of=[//fileserver/file]แต่ในเวลานั้นสำเนาต้นฉบับของฉันใช้แฟลชไดรฟ์ 4GB


2
คำตอบทั้งหมดด้านล่างไม่ถูกต้องยกเว้น @sudoer dd conv=sparseคำตอบที่ถูกต้องคือการใช้งาน
บาฮามาต

@bahamat, ไม่, gzip ดีกว่าเนื่องจากมันจะบีบอัดข้อมูล
psusi

1
นั่นไม่ใช่สิ่งเดียวกับหร็อมแหร็ม
บาฮามาต

@bahamat คำถามไม่ได้ถามเฉพาะสำหรับ sprase วิธีทำให้ภาพใช้พื้นที่น้อยลง
psusi

คำตอบ:


37

ย้อนกลับไปในวันที่ฉันพบปัญหาที่คล้ายกันกับการกระจาย Linux ที่ฝังตัว - กำจัดขยะทั้งหมดก่อนที่จะบีบอัดภาพ

dd if=/dev/zero of=asdf.txt. รอจนกว่าจะตาย ลบ asdf.txt

คุณเพิ่งเขียนเลขศูนย์ลงบนพื้นที่ว่างทั้งหมดบนอุปกรณ์

ตอนนี้นำภาพดิสก์และเรียกใช้ผ่าน gzip Voila รูปกระจัดกระจาย

อาจไม่ได้ขนาดที่ดีมากและอาจทำให้เกิดปัญหาหากคุณต้องการเขียนลงดิสก์ แต่จริง ๆ

คุณสามารถนำสแน็ปช็อต rsync ของดิสก์ไปยังไดรฟ์ข้อมูลอื่นได้ศูนย์นั้นนำภาพดิสก์นั้นไปใช้

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


ถ้าฉันเรียกใช้ผ่าน gzip ฉันจะต้องคลายซิปก่อนใช้หรือไม่ และโดยการเรียกใช้ผ่าน gzip ฉันเพียงแค่ไพพ์ระหว่างกระบวนการ dd หรือไม่
Jonathan Henson

3
ใช่. dd if=sda2.gz | gunzip > /dev/sda2และdd if=/dev/sda2 | gzip > sda2.gz
Rob Bos

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

หากสื่อทางกายภาพเป็น SSD ตอนนี้อาจคิดว่ามีการใช้งานทุกส่วนของอุปกรณ์ สิ่งนี้จะช่วยให้ SSD มีเซ็กเตอร์น้อยลงในการทำงานและอาจลดประสิทธิภาพลง หากไดรเวอร์และเฟิร์มแวร์รองรับ TRIM เงื่อนไขนั้นจะมีผลจนกว่าคุณจะลบไฟล์อีกครั้ง หากคุณเก็บไฟล์ไว้ในขณะที่คุณสร้างภาพคุณจะต้องลบไฟล์อีกครั้งหลังจากเรียกคืนรูปภาพ อาจมีประโยชน์หากภาพถูกกู้คืนเป็น SSD
kasperd

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

17

สมมติว่าคุณต้องการที่จะประหยัด/dev/sdXNไป/tgtfs/image.rawและคุณเป็นราก:

  1. mkdir /srcfs && mount /dev/sdXN /srcfs

  2. ใช้ zerofill หรือเพียงแค่: dd if=/dev/zero of=/srcfs/tmpzero.txtเติมบล็อกที่ไม่ได้ใช้ด้วยศูนย์ (รอให้เต็มระบบไฟล์จนหมดrm /srcfs/tmpzero.txt)

  3. ถ่ายภาพด้วย dd และใช้ conv = sparse เพื่อต่อยเลขศูนย์แบบทันที: dd conv=sparse if=/dev/sdxn of=/tgtfs/image.raw

หากคุณต้องการใช้การบีบอัดคุณไม่จำเป็นต้องเจาะศูนย์ด้วย dd เนื่องจากศูนย์บล็อกนั้นสามารถบีบอัดได้สูง:

dd if=/dev/sdxn | gz -c | dd of=/tgtfs/image.raw

PS: คุณควรทราบว่านี่ไม่ใช่ความคิดที่ดีในสื่อเก็บข้อมูลที่ใช้หน่วยความจำแฟลช (เช่นระบบไฟล์ต้นทางของคุณเป็น SSD)


5
นี่คือคำตอบที่ถูกต้อง dd conv=sparseใช้
บาฮามาต

1
เกิดอะไรขึ้นกับการทำเช่นนี้กับที่เก็บข้อมูลแฟลช
Dan

2
@Dan (ขึ้นอยู่กับการออกแบบฮาร์ดแวร์และซอฟต์แวร์และการกำหนดค่า) อาจทำให้ SSD ของคุณเขียนได้นานและลดอายุการใช้งาน และโดยทั่วไปแล้วมันก็โอเคสำหรับการย้ายข้อมูลจากดิสก์เก่าไปยังดิสก์ใหม่ (หรือสิ่งที่ OP ต้องการทำ) แต่การสำรองข้อมูลระดับดิสก์ / พาร์ติชันนั้นไม่ใช่ทางออกที่ดีสำหรับการสำรองและกู้คืนปกติแม้แต่ใน HDD การสำรองข้อมูลระดับไฟล์ (เช่นการจัดการไฟล์จากระบบไฟล์หนึ่งไปสู่อีกระบบหนึ่ง) หรือการสำรองข้อมูลระดับระบบไฟล์ (ด้วยระบบไฟล์เช่น BTRFS พร้อมbtrfs snapshotและbtrfs sendเครื่องมือ) เป็นวิธีที่ดีกว่า IMHO
Sudoer

คำแนะนำ: หากคุณไม่มีgzในของคุณPATH(อย่างที่ฉันไม่ได้ทำใน GParted Live) คุณสามารถใช้gzip -cแทนได้
XtraSimplicity

11

ใช้ dd พร้อมตัวเลือกการนับ

ในกรณีของคุณคุณกำลังใช้ fdisk ดังนั้นฉันจะใช้วิธีการนั้น สร้าง "sudo fdisk -l" ของคุณแล้ว:

    Disk /dev/sda: 64.0 GB, 64023257088 bytes
    255 heads, 63 sectors/track, 7783 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk identifier: 0x0000e4b5

    Device Boot      Start         End      Blocks   Id  System
    /dev/sda1   *           1          27      209920   83  Linux
    Partition 1 does not end on cylinder boundary.
    /dev/sda2              27         525     4000768    5  Extended
    Partition 2 does not end on cylinder boundary.
    /dev/sda5              27         353     2621440   83  Linux
    /dev/sda6             353         405      416768   83  Linux
    /dev/sda7             405         490      675840   83  Linux
    /dev/sda8             490         525      282624   83  Linux

สองสิ่งที่คุณควรทราบคือ 1) ขนาดของหน่วยและ 2) คอลัมน์ "สิ้นสุด" ในกรณีของคุณคุณมีถังที่มีค่าเท่ากับ 8225280 ไบต์ ในคอลัมน์ "สิ้นสุด" sda8 สิ้นสุดที่ 525 (ซึ่งคือ 525 [หน่วย] * 16065 * 512 = ~ 4.3GB)

dd สามารถทำสิ่งต่างๆมากมายเช่นเริ่มจากออฟเซ็ตหรือหยุดหลังจากจำนวนบล็อกที่ระบุ เราจะทำหลังโดยใช้ตัวเลือกการนับในวว คำสั่งจะปรากฏดังนี้:

    sudo dd if=/dev/sda of=/your_directory/image_name.iso bs=8225280 count=526

โดยที่ -bs คือขนาดบล็อก (เป็นการง่ายที่สุดในการใช้หน่วยที่ fdisk ใช้ แต่หน่วยใด ๆ จะทำตราบเท่าที่ตัวเลือกการนับถูกประกาศในหน่วยเหล่านี้) และการนับเป็นจำนวนหน่วยที่เราต้องการคัดลอก (หมายเหตุ ที่เราเพิ่มการนับ 1 เพื่อจับบล็อกสุดท้าย)


FYI: หากต้องการแสดงหน่วยเป็นรูปทรงกระบอกให้ใช้fdisk -l -u=cylinders /dev/sda
xinthose

3
ทำไมนี่ไม่ใช่คำตอบที่ยอมรับ? ดูเหมือนว่าจะเป็นตัวเลือกที่รบกวนน้อยที่สุดเนื่องจากไม่ได้แก้ไขแหล่งที่มา
user33326

@ user33326 เพราะคำตอบนี้ดีสำหรับการไม่คัดลอกพื้นที่ว่างบนไดรฟ์ไม่ใช่พื้นที่ว่างที่ไม่ได้ใช้ภายในพาร์ติชั่นซึ่งเป็นสิ่งที่ OP ให้ความสำคัญ
GDorn

8

ในขณะ/dev/zeroที่ใช้เนื้อที่ว่างบนดิสก์และใช้dd conv=sparse/ gz -cเป็นไปได้บนดิสก์ขนาดใหญ่ที่มีพื้นที่ว่างที่ทำงานใน 100s ของ GB การใช้งาน/dev/zeroช้าลงอย่างเจ็บปวด - ไม่ต้องพูดถึงว่าเป็นคำตอบอื่น ๆ ที่บันทึกไว้/dev/zeroSDD จนถึง EOF

นี่คือสิ่งที่ฉันทำเมื่อฉันพบสถานการณ์เช่นนี้:

  • บน lubuntu live CD เคยใช้gpartedในการ 'ย่อขนาด' ดิสก์ให้มีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้

  • ใช้
    dd bs=1M count=<size_in_MBs> if=/dev/sdX | gzip -c --fast| dd of=/path/to/image.gz เพื่อสร้างภาพที่บีบอัดอย่างรวดเร็ว (ไม่จำเป็นต้องบอกว่าคุณอาจต้องการข้ามการบีบอัดหากคุณมีพื้นที่เพียงพอในการจัดเก็บข้อมูลดิบ (หรือมีแนวโน้มที่จะลดการโหลด CPU)

  • ใช้
    dd if=/path/to/image.gz | gunzip -c | dd bs=1M of=/dev/sdY เพื่อคัดลอกข้อมูลกลับไปยังดิสก์อื่น
  • ใช้gpartedอีกครั้งเพื่อ 'ขยาย' พาร์ติชัน

ฉันไม่ได้ลองหลายพาร์ติชั่น แต่ฉันเชื่อว่ากระบวนการข้างต้นสามารถปรับให้คัดลอก 'พาร์ติชั่น' ถ้าพาร์ติชั่นตารางบนดิสก์ปลายทางถูกสร้างขึ้นก่อนและคัดลอกเฉพาะข้อมูลที่อยู่ในพาร์ติชั่นdd- การอ่าน / เขียนskip/ seekตัวเลือกของddตามลำดับ) จะต้องตามความเหมาะสม


1
นี่คือคำตอบที่แท้จริงเพียงใช้countพารามิเตอร์
Gordy

7

คุณทำไม่ได้ ddเป็นเครื่องมือระดับต่ำมากและไม่มีความแตกต่างระหว่างไฟล์และพื้นที่ว่าง

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


7
สมมติว่าไม่มีที่ว่างก่อนหน้านี้ คุณสามารถเติมเต็มพื้นที่ว่างก่อนเพื่อให้แน่ใจว่าการบีบอัดทำงานได้ตามที่คาดไว้
Sirex

1
จริง และจะทำให้กระบวนการยุ่งยากและใช้เวลานานขึ้น
c2h5oh

6

สมมติว่าส่วนที่เหลือของไดรฟ์นั้นว่างเปล่า (ศูนย์ทั้งหมด) คุณสามารถส่ง DD ของคุณผ่าน gzip ซึ่งควรจะบีบอัดพื้นที่ว่างเปล่าค่อนข้างดี คุณสามารถใช้เครื่องมือเช่นzerofreeเพื่อให้แน่ใจว่าพื้นที่ว่างของคุณว่างเปล่าจริง ๆ ดังนั้นมันจึงบีบอัดได้ดี

หากคุณใช้เครื่องมือเช่นpartimage , clonezillaหรือเครื่องมืออื่น ๆ ของ linux clone พวกเขาจะจัดการส่วนนี้ให้คุณโดยอัตโนมัติ


partimage และ clonezilla นั้นฉลาดพอที่จะข้ามการอ่านพื้นที่ว่างได้แทนที่จะพึ่งคุณเขียนเลขศูนย์จากนั้นก็ให้ dd หรือ gzip หล่นหรือบีบอัดศูนย์หลังจากอ่านพวกมันมา
psusi

2

คำตอบที่ยอมรับไม่ถูกต้อง ฉันเห็นด้วยกับความคิดเห็นข้างต้น ฉันใช้ddพร้อมพารามิเตอร์countเพื่อสำรองดิสก์ของฉันบนฐานปกติ เพียงแค่แทนที่ BACKUP_FOLDER และตัวอักษรของอุปกรณ์ของคุณด้วย "X":

กำหนดบล็อกที่ใช้ล่าสุดของดิสก์:

ct=$(fdisk -l | awk '$1 == "/dev/sdX" { print $3 }')

จากนั้นโคลนดิสก์ (ยกเว้นพื้นที่ว่างเปล่า):

dd if=/dev/sdX bs=512 count=$ct | gzip > BACKUP_FOLDER/sdX_$(date +"%Y-%m-%d").img.gz >>"$LOG"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.