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

Мені потрібно створити зображення для зберігання на нашому файловому сервері для використання у миготі інших пристроях, які ми виготовляємо, тому я хочу лише використаний простір (лише близько 4 Гб). Я хочу зберегти mbr і т. Д. ... оскільки цей пристрій повинен бути готовим до завантаження, як тільки копія закінчена.

Будь-які ідеї? Я раніше використовував dd if=/dev/sda of=[//fileserver/file], але в той час моя головна копія знаходилася на 4 Гб флеш-ідеї.


2
Усі наведені нижче відповіді помилкові, окрім @sudoer. Правильна відповідь - використовувати dd conv=sparse.
bahamat

@bahamat, ні, gzip краще, оскільки він буде стискати дані.
psusi

1
Це не те саме, що рідкісне.
bahamat

@bahamat, питання не задається спеціально для sprase; як зробити так, щоб зображення займало менше місця.
psusi

Відповіді:


37

Ще в той день, коли я зіткнувся з подібною проблемою з вбудованими дистрибутивами Linux - позбудьтеся від усіх мотлоху, перш ніж стискати зображення.

dd if=/dev/zero of=asdf.txt. Почекайте, поки він помре. Видалити asdf.txt.

Ви тільки що записали нулі на весь вільний простір на пристрої.

Тепер візьміть образ диска і запустіть його через gzip. Вуале, розріджене зображення.

Напевно, не дуже масштабує і може спричинити проблеми, якщо вам потрібно записати на диск, але ей.

Ви можете зробити знімок rsync диска на інший обсяг, нульовий, а потім взяти це зображення диска.

Примітка. Може бути небезпечним для SSD, користувач повинен врахувати цю операцію, щоб здійснити її.


якщо я запускаю його через gzip, чи доведеться розпаковувати його, перш ніж використовувати його? І запускаючи його через gzip, я просто передаю його під час процесу dd?
Джонатан Хенсон

3
Так. dd if=sda2.gz | gunzip > /dev/sda2іdd if=/dev/sda2 | gzip > sda2.gz
Роб Бос

3
"Ви тільки що записали нулі на весь вільний простір на пристрої". Ви маєте на увазі розділ, а не пристрій, я думаю. Отже, вам потрібно буде запустити цю команду з ofконтуром для кожного розділу.
jiggunjer

Якщо фізичний носій являє собою SSD, він може вважати, що використовується кожен сектор на пристрої. Це дасть SSD менше запасних секторів для роботи і, можливо, зниження продуктивності в результаті. Якщо в драйвері та прошивці є підтримка TRIM, ця умова застосовуватиметься лише до того, як ви знову видалите файл. Якщо ви тримаєте файл на місці під час створення зображення, після відновлення зображення вам доведеться знову видалити файл. Це може бути корисно, якщо зображення буде відновлено на SSD.
kasperd

Майте на увазі кілька додаткових проблем. Оскільки цей метод вимагає встановлення файлової системи для читання-запису, існує ризик, що зміни в базовій файловій системі під час копіювання ведуть до непослідовного зображення. Одного разу я побачив, що отримана копія буде настільки непослідовною, що fsck насправді буде сегментарно при спробі виправити невідповідності копії. Також заповнення пристрою може призвести до відмови інших процесів, які потребують запису на носій.
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
Що поганого в цьому на флеш-пам’яті?
Дан

2
@Dan (залежно від дизайну та конфігурації програмного забезпечення та програмного забезпечення) може призвести до великого запису на ваш SSD і скорочення терміну його служби. і загалом, це нормально для переміщення даних зі старого диска на новий (або те, що хотів зробити ОП), але резервне копіювання рівня диска / розділу не є хорошим рішенням для регулярного резервного копіювання та відновлення навіть на жорстких дисках. резервне копіювання рівня файлів (тобто копіювання файлів з однієї файлової системи в іншу) або резервне копіювання на рівні файлової системи (з файловими системами, такими як BTRFS, btrfs snapshotта btrfs sendінструментами) - краще рішення IMHO.
Судер

Підказка: Якщо у вас немає 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,3 ГБ)

dd може робити багато речей, наприклад, починаючи після зміщення або зупиняючись після певної кількості блоків. Ми зробимо останнє, використовуючи варіант підрахунку в dd. Команда з'явиться наступним чином:

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

Де -bs - розмір блоку (найпростіше використовувати одиницю, яку використовує fdisk, але будь-яка одиниця буде робити це, поки опція підрахунку оголошена в цих одиницях), а count - кількість одиниць, яку ми хочемо скопіювати (зверніть увагу що ми збільшуємо число на 1, щоб захопити останній блок).


FYI: щоб показати одиниці в циліндрах, використовуйтеfdisk -l -u=cylinders /dev/sda
xinthose

3
Чому це не прийнята відповідь? Здається, це найменш нав'язливий варіант, оскільки він не змінює джерело.
користувач33326

@ user33326, оскільки ця відповідь хороша тим, що не копіює нерозподілений простір на диску, а не невикористаний простір у розділах, про що піклується ОП.
GDorn

8

Хоча /dev/zeroвикористання вільного дискового простору та використання dd conv=sparse/ gz -cможливе, на величезних дисках з порожнім простором, що працює в 100 Гб, /dev/zeroінгінг є болісно повільним - не кажучи вже про те, що, як відзначали інші відповіді, /dev/zeroпро SDD до EOF.

Ось що я зробив, коли зіткнувся з цією ситуацією:

  • На живому компакт-диску lubuntu, який використовується gpartedдля зменшення диска до мінімально можливого розміру, залишаючи залишок місця нерозподіленим

  • Використовується
    dd bs=1M count=<size_in_MBs> if=/dev/sdX | gzip -c --fast| dd of=/path/to/image.gz для створення швидко стисненого зображення (не потрібно говорити, що ви можете пропустити стиснення, якщо у вас є достатньо місця для зберігання необроблених даних (або ви іншим чином схильні зменшити завантаження процесора)

  • Використовується
    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
Припускаючи, що вільний простір раніше не використовувався. Ви можете спочатку заповнити вільний простір, щоб забезпечити спрацювання, як очікувалося.
Сірекс

1
Правда. І це лише ускладнює процес і змушує зайняти ще більше часу.
c2h5oh

6

Якщо припустити, що решта накопичувача порожня (усі нулі), ви можете передати ваш DD через gzip, який повинен досить добре стиснути порожній простір. Ви можете використовувати такий інструмент, як zerofree, щоб переконатися, що ваш порожній простір справді порожній, щоб він добре стискав.

Якщо ви використовуєте такий інструмент, як partimage , clonezilla або якийсь інший інструмент для клонування Linux, вони б обробляли більшість із вас автоматично.


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"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.