คำสั่งของฉันคือการโคลนไดรฟ์ที่ดีที่สุด?


16

ฉันอ่านครึ่งชั่วโมงเพื่อเตรียมพร้อมที่จะโคลนฮาร์ดไดรฟ์ของฉัน มีหลายพาร์ติชันรวมถึงพาร์ติชัน Windows ฉันจะซื้อฮาร์ดไดรฟ์ภายนอกที่มีขนาดใหญ่มากสำหรับการสำรองข้อมูล ฉันต้องการใช้โคลนนี้เพื่อกู้คืนไดรฟ์ทั้งหมดในกรณีที่มีข้อผิดพลาดเกิดขึ้น (ฉันกำลังจะทำการสับระบบปฏิบัติการอีกครั้ง) ฉันต้องการเรียนรู้วิธีการทำสิ่งนี้โดยใช้ dd เนื่องจากฉันชอบเครื่องมือระดับต่ำที่ไม่ต้องการติดตั้งอะไรเลย

ฉันพบรหัสที่เป็นประโยชน์ต่อไปนี้จากฟอรัม ubuntu (ป้อนจาก root shell โดยใช้ live CD):

dd if=/dev/hda of=/dev/hdb & pid=$!
while kill -USR1 $pid; do sleep 1; done

(ฉันรู้ว่าฉันจะต้องแก้ไขตำแหน่งอินพุตและเอาต์พุต) อย่างไรก็ตามฉันมีสองคำถาม อันแรกคือ noobie มาก: คำสั่งนี้ถูกแบ่งข้ามสองบรรทัด แน่นอนเมื่อฉันกด Enter หลังจากเครื่องหมายอัศเจรีย์มันจะเริ่มต้นกระบวนการหรือไม่

สองในไซต์อื่น ๆ ที่แนะนำให้ป้อนขนาดบล็อก แบบนี้:

# dd if=/dev/hda conv=sync,noerror bs=64K of=/mnt/sda1/hda.img

ฉันไม่รู้อะไรเลยเกี่ยวกับขนาดบล็อก 64K ใช่ไหม ดูเหมือนว่าขนาดบล็อกของฉันคือ 512 ไบต์จากสิ่งต่อไปนี้เอาต์พุตของ sudo fdisk -ul:

Disk /dev/sda: 750.2 GB, 750156374016 bytes
255 heads, 63 sectors/track, 91201 cylinders, total 1465149168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk identifier: 0xc3ffc3ff

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *          63   143364059    71681998+   7  HPFS/NTFS/exFAT
Partition 1 does not start on physical sector boundary.
/dev/sda2       976867328  1465147391   244140032    7  HPFS/NTFS/exFAT
/dev/sda3       143364094   976867327   416751617    5  Extended
Partition 3 does not start on physical sector boundary.
/dev/sda5       143364096   162895871     9765888   82  Linux swap / Solaris
/dev/sda6       162897920   205864959    21483520   83  Linux
/dev/sda7       205867008   976867327   385500160   83  Linux

Partition table entries are not in disk order

Disk /dev/mapper/cryptswap1: 10.0 GB, 10000269312 bytes
255 heads, 63 sectors/track, 1215 cylinders, total 19531776 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk identifier: 0x433bb3a7

Disk /dev/mapper/cryptswap1 doesn't contain a valid partition table

ขอขอบคุณ.


คุณลองแบบง่าย ๆdd if=/dev/hda of=hdbหรือไม่? นี่คือคำตอบที่แสดงรายละเอียดบางอย่างรวมถึงรันไทม์สำหรับ 160 GB: askubuntu.com/questions/435694/…
SDsolar

Ubuntu รุ่นล่าสุดใช้ coreutils v.8.24 ขึ้นไปซึ่งddรวมถึงสวิตช์ความคืบหน้าตามที่กล่าวไว้ที่นี่
Elder Geek

คำตอบ:


22

ความคืบหน้า

คำสั่งที่คุณระบุไว้

dd if=/dev/hda of=/dev/hdb & pid=$!
while kill -USR1 $pid; do sleep 1; done

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

บล็อคด้วยdd: การจัดตำแหน่งและประสิทธิภาพ

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

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

จากนั้นพิจารณาการใช้งาน CPU ธรรมดาด้วยเมื่อจัดการกับการดำเนินการขนาดเล็กจำนวนมาก การเพิ่มประสิทธิภาพเป็นเมกะไบต์ต่อครั้งเมื่อคัดลอกข้อมูลจำนวนมาก

วิธีปฏิบัติที่ดีที่สุดของฉันคือเริ่มต้นด้วย 1MB เนื่องจากเป็นชุดที่ดีที่สุดของการติดตั้งส่วนใหญ่รวมถึงขนาด RAID Stripe ขนาด LVM และอื่น ๆ บนแล็ปท็อปที่ใช้ SSD ฉันมักจะเห็นการปรับปรุงเล็กน้อยโดยใช้ 10MB เป็นขนาดบล็อก ไม่เห็นอีกต่อไปในฮาร์ดไดรฟ์ทางกายภาพของฉัน

บล็อกสุดท้าย

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

18335302+0 records out

+0หมายถึงว่ามันเป็นตรงที่+1หมายถึงว่ามันไม่ได้ ไม่ใช่เรื่องใหญ่.

ดูสิ่งนี้ด้วย


1
ว้าวช่างเป็นคำตอบที่ละเอียดถี่ถ้วน ขอบคุณมากที่สละเวลาในการทำมัน ฉันจะอัปเดตคำถามเดิมพร้อมลิงก์ไปยังแหล่งที่มาของฉัน ฉันจะไปด้วย 1 MB แล้ว ดังนั้นคำสั่งของฉันจะเป็นเช่นนี้ฉันถูกไหม # dd if=/dev/hda conv=sync,noerror bs=1MB of=/mnt/sda1/hda.img & pid=$! while kill -USR1 $pid; do sleep 1; done
ชุดจอห์นสัน

2
@oldmankit ฉันจะทำbs=1Mตามที่เป็นพลังของ 2 แทนที่จะbs=1MBเป็นพลังของ 10 แต่เพียงใช้มาตรฐานในระบบของคุณถ้าคุณสามารถดูสิ่งที่ดีที่สุด
gertvdijk

4
โปรดทราบว่าตามที่ระบุไว้ที่นี่ตั้งแต่เปิดตัว coreutils> = 8.24 (ค่าเริ่มต้นใน Ubuntu Xenial 16.04 ขึ้นไป) ไม่จำเป็นต้องใช้kill -USR1 $piddd อีกต่อไปตอนนี้มีรายงานความคืบหน้าพร้อมใช้งานโดยการเพิ่มstatus=progressสวิตช์
Elder Geek

10

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

สิ่งหนึ่งที่ค่อนข้างน่าเชื่อถือในฮาร์ดแวร์สมัยใหม่คือขนาดบล็อกเริ่มต้นที่ 512 ไบต์มีแนวโน้มที่จะมีขนาดที่ช้ากว่าทางเลือกที่เหมาะสมกว่า เมื่อมีข้อสงสัยฉันพบว่า 64K เป็นค่าเริ่มต้นที่ค่อนข้างแข็งแกร่งในปัจจุบัน แม้ว่าโดยปกติแล้ว 64K จะไม่ใช่ขนาดบล็อกที่ดีที่สุด แต่จากประสบการณ์ของฉันมันมักจะมีประสิทธิภาพมากกว่าค่าเริ่มต้น 64K ยังมีประวัติที่ค่อนข้างแข็งแกร่งในการเป็นนักแสดงที่น่าเชื่อถือ: คุณสามารถค้นหาข้อความจากรายชื่อผู้รับจดหมายของ Eug-Lugประมาณปี 2545 แนะนำขนาดบล็อก 64K

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

dd_obs_test.sh:

#!/bin/bash

# Since we're dealing with dd, abort if any errors occur
set -e

TEST_FILE=${1:-dd_obs_testfile}
TEST_FILE_EXISTS=0
if [ -e "$TEST_FILE" ]; then TEST_FILE_EXISTS=1; fi
TEST_FILE_SIZE=134217728

if [ $EUID -ne 0 ]; then
  echo "NOTE: Kernel cache will not be cleared between tests without sudo. This will likely cause inaccurate results." 1>&2
fi

# Header
PRINTF_FORMAT="%8s : %s\n"
printf "$PRINTF_FORMAT" 'block size' 'transfer rate'

# Block sizes of 512b 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M 2M 4M 8M 16M 32M 64M
for BLOCK_SIZE in 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864
do
  # Calculate number of segments required to copy
  COUNT=$(($TEST_FILE_SIZE / $BLOCK_SIZE))

  if [ $COUNT -le 0 ]; then
    echo "Block size of $BLOCK_SIZE estimated to require $COUNT blocks, aborting further tests."
    break
  fi

  # Clear kernel cache to ensure more accurate test
  [ $EUID -eq 0 ] && [ -e /proc/sys/vm/drop_caches ] && echo 3 > /proc/sys/vm/drop_caches

  # Create a test file with the specified block size
  DD_RESULT=$(dd if=/dev/zero of=$TEST_FILE bs=$BLOCK_SIZE count=$COUNT conv=fsync 2>&1 1>/dev/null)

  # Extract the transfer rate from dd's STDERR output
  TRANSFER_RATE=$(echo $DD_RESULT | \grep --only-matching -E '[0-9.]+ ([MGk]?B|bytes)/s(ec)?')

  # Clean up the test file if we created one
  if [ $TEST_FILE_EXISTS -ne 0 ]; then rm $TEST_FILE; fi

  # Output the result
  printf "$PRINTF_FORMAT" "$BLOCK_SIZE" "$TRANSFER_RATE"
done

ดูบน GitHub

ฉันได้ทดสอบสคริปต์นี้บนระบบ Debian (Ubuntu) และบน OSX Yosemite เท่านั้นดังนั้นจึงอาจต้องใช้เวลาปรับแต่งเพื่อให้ทำงานกับ Unix รสชาติอื่น ๆ

โดยค่าเริ่มต้นคำสั่งจะสร้างไฟล์ทดสอบชื่อdd_obs_testfileในไดเรกทอรีปัจจุบัน หรือคุณสามารถระบุพา ธ ไปยังไฟล์ทดสอบที่กำหนดเองโดยระบุพา ธ หลังชื่อสคริปต์:

$ ./dd_obs_test.sh /path/to/disk/test_file

ผลลัพธ์ของสคริปต์คือรายการขนาดบล็อกทดสอบและอัตราการถ่ายโอนที่เกี่ยวข้องดังนี้:

$ ./dd_obs_test.sh
block size : transfer rate
       512 : 11.3 MB/s
      1024 : 22.1 MB/s
      2048 : 42.3 MB/s
      4096 : 75.2 MB/s
      8192 : 90.7 MB/s
     16384 : 101 MB/s
     32768 : 104 MB/s
     65536 : 108 MB/s
    131072 : 113 MB/s
    262144 : 112 MB/s
    524288 : 133 MB/s
   1048576 : 125 MB/s
   2097152 : 113 MB/s
   4194304 : 106 MB/s
   8388608 : 107 MB/s
  16777216 : 110 MB/s
  33554432 : 119 MB/s
  67108864 : 134 MB/s

(หมายเหตุ: หน่วยของอัตราการถ่ายโอนจะแตกต่างกันไปตามระบบปฏิบัติการ)

ในการทดสอบที่ดีที่สุดอ่านขนาดบล็อกคุณสามารถใช้มากหรือน้อยกระบวนการเดียวกัน แต่แทนที่จะอ่านจากและการเขียนไปยังดิสก์ที่คุณต้องการอ่านจากดิสก์และการเขียนไปยัง/dev/zero /dev/nullสคริปต์ในการทำเช่นนี้อาจมีลักษณะดังนี้:

dd_ibs_test.sh:

#!/bin/bash

# Since we're dealing with dd, abort if any errors occur
set -e

TEST_FILE=${1:-dd_ibs_testfile}
if [ -e "$TEST_FILE" ]; then TEST_FILE_EXISTS=$?; fi
TEST_FILE_SIZE=134217728

# Exit if file exists
if [ -e $TEST_FILE ]; then
  echo "Test file $TEST_FILE exists, aborting."
  exit 1
fi
TEST_FILE_EXISTS=1

if [ $EUID -ne 0 ]; then
  echo "NOTE: Kernel cache will not be cleared between tests without sudo. This will likely cause inaccurate results." 1>&2
fi

# Create test file
echo 'Generating test file...'
BLOCK_SIZE=65536
COUNT=$(($TEST_FILE_SIZE / $BLOCK_SIZE))
dd if=/dev/urandom of=$TEST_FILE bs=$BLOCK_SIZE count=$COUNT conv=fsync > /dev/null 2>&1

# Header
PRINTF_FORMAT="%8s : %s\n"
printf "$PRINTF_FORMAT" 'block size' 'transfer rate'

# Block sizes of 512b 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M 2M 4M 8M 16M 32M 64M
for BLOCK_SIZE in 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864
do
  # Clear kernel cache to ensure more accurate test
  [ $EUID -eq 0 ] && [ -e /proc/sys/vm/drop_caches ] && echo 3 > /proc/sys/vm/drop_caches

  # Read test file out to /dev/null with specified block size
  DD_RESULT=$(dd if=$TEST_FILE of=/dev/null bs=$BLOCK_SIZE 2>&1 1>/dev/null)

  # Extract transfer rate
  TRANSFER_RATE=$(echo $DD_RESULT | \grep --only-matching -E '[0-9.]+ ([MGk]?B|bytes)/s(ec)?')

  printf "$PRINTF_FORMAT" "$BLOCK_SIZE" "$TRANSFER_RATE"
done

# Clean up the test file if we created one
if [ $TEST_FILE_EXISTS -ne 0 ]; then rm $TEST_FILE; fi

ดูบน GitHub

ข้อแตกต่างที่สำคัญในกรณีนี้คือไฟล์ทดสอบเป็นไฟล์ที่เขียนโดยสคริปต์ อย่าชี้คำสั่งนี้ที่ไฟล์ที่มีอยู่มิฉะนั้นไฟล์ที่มีอยู่จะถูกเขียนทับด้วยข้อมูลแบบสุ่ม!

สำหรับฮาร์ดแวร์เฉพาะของฉันฉันพบว่า 128K เป็นขนาดบล็อกอินพุตที่ดีที่สุดบน HDD และ 32K นั้นดีที่สุดสำหรับ SSD

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

โพสต์ StackOverflow นี้อาจมีประโยชน์เช่นกัน: dd: วิธีคำนวณขนาดบล็อกที่เหมาะสมที่สุด?


สอนให้คนหาปลา = +1
HackSlash

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