dd (Русский) - ArchWiki

Jump to content
From ArchWiki

Состояние перевода: На этой странице представлен перевод статьи dd. Дата последней синхронизации: 2 февраля 2022. Вы можете помочь синхронизировать перевод, если в английской версии произошли изменения.

Ссылки по теме

- Клонирование диска
- Установочный образ на USB-накопителе#Через dd
- Benchmarking#dd
- Securely wipe disk#dd

dd — это основная утилита, основной задачей которой является конвертация и копирование файлов.

Как и cp, по умолчанию dd делает точную копию файла, но позволяет контролировать параметры ввода-вывода на низком уровне.

Подробности можно почитать в dd(1) или полной документации.

Совет: По умолчанию dd ничего не пишет в консоль в процессе работы. Чтобы следить за процессом, можно использовать опцию `status=progress`.
Важно: Будьте крайне осторожны при использовании dd, так как её использование может необратимо уничтожить данные.

## Установка

dd входит в состав GNU coreutils. Другие утилиты из этого пакета описаны в статье Основные утилиты.

## Клонирование диска и восстановление

Команда dd — это простой, но универсальный и мощный инструмент. Она может использоваться для копирования, блок за блоком, независимо от типа файловой системы или операционной системы. Нередко dd используется в LiveCD.

Важно: Как и с любыми командами подобного рода, при использовании dd нужно быть очень осторожным; она может уничтожить данные. Запомните опции, задающие входной файл (`if=`) и выходной файл (`of=`), и не меняйте их местами! Всегда проверяйте, что целевой диск или раздел (`of=`) имеет равный или больший размер, чем исходный (`if=`).

### Клонирование раздела

Копирование раздела 1 на диске `/dev/sda` в раздел 1 на диске `/dev/sdb`:

    # dd if=/dev/sda1 of=/dev/sdb1 bs=64K conv=noerror,sync status=progress

Примечание: Проверяйте существование файла целевого устройства (в данном примере `sdb1`). Если он не существует, то dd создаст новый файл, который будет занимать место в вашей файловой системе.

### Клонирование всего диска

Копирование физического диска `/dev/sda` в диск `/dev/sdb`:

    # dd if=/dev/sda of=/dev/sdb bs=64K conv=noerror,sync status=progress

Эта команда скопирует диск целиком, в том числе таблицу разделов, загрузчик, разделы, UUID и данные.

- `bs=` устанавливает размер блока. По умолчанию 512 байт, что является «классическим» размером блока для жёстких дисков с начала 1980-х годов, но не самым удобным. Используйте большее значение, 64K или 128K. Также прочитайте предупреждение ниже, потому что это не просто «размер блока» — это также влияет на обработку ошибок чтения. Смотрите [1] и [2] для получения подробной информации и определения наилучшего значения bs для вашего случая.
- `noerror` указывает dd продолжить работу, игнорируя все ошибки чтения. По умолчанию dd прекращает работу при любой ошибке.
- `sync` заполняет входные блоки нулями, если были ошибки чтения, чтобы смещения данных оставались правильными.
- `status=progress` показывает статистику передачи данных, которая позволяет оценить время завершения.

Примечание: Размер блока, который вы указываете, влияет на то, как обрабатываются ошибки чтения (смотрите ниже). Для восстановления данных используйте ddrescue.

Утилита dd технически имеет «размер входного блока» (IBS) и «размер выходного блока» (OBS). Когда вы устанавливаете `bs`, вы фактически устанавливаете и IBS, и OBS. Обычно, если размер блока, скажем, 1 МиБ, dd считывает 1024×1024 байт и записывает столько же байт. Но если произойдет ошибка чтения, всё пойдет не так. Многие думают, что dd «заполнит ошибки чтения нулями», если вы используете опции `noerror,sync`, но это не так. dd, согласно документации, дополнит размер OBS до размера IBS после завершения чтения, что означает добавление нулей в конце блока. То есть, весь 1 МиБ будет испорчен из-за одной ошибки чтения в 512 байт в начале чтения: 12ERROR89 станет 128900000 вместо 120000089.

Если вы уверены, что ваш диск не содержит ошибок, вы можете использовать больший размер блока, что увеличит скорость копирования в несколько раз. Например, изменение bs с 512 до 64K изменило скорость копирования с 35 МБ/с до 120 МБ/с на простой системе Celeron 2,7 ГГц. Но имейте в виду, что ошибки чтения на исходном диске будут в конечном итоге выглядеть как ошибки блоков на целевом диске, то есть одна ошибка чтения 512 байт испортит весь выходной блок размером 64 КиБ.

Примечание:

- Чтобы сделать UUID файловых систем ext2/3/4 снова уникальными после копирования, используйте `tune2fs /dev/sdXY -U random` для каждого раздела. Для разделов подкачки используйте `mkswap /dev/sdXY`.
- Если вы копируете GPT-диск, вы можете использовать sgdisk для рандомизации GUID диска и разделов и восстановления их уникальности.
- Изменения таблицы разделов, которые внёс dd на целевом диске, не регистрируются ядром. Чтобы попросить ядро перечитать таблицы разделов без перезагрузки, можно использовать утилиту partprobe (часть GNU Parted).

### Резервное копирование таблицы разделов

Смотрите fdisk (Русский)#Резервное копирование и восстановление таблицы разделов или GPT fdisk (Русский)#Резервное копирование и восстановление таблицы разделов.

### Создание образа диска

Загрузитесь в LiveCD и убедитесь, что разделы исходного диска не примонтированы.

Затем смонтируйте целевой диск и запишите на него резервную копию:

    # dd if=/dev/sda conv=sync,noerror bs=64K | gzip -c  > /путь/к/копии.img.gz

При необходимости (например, если результирующие файлы будут храниться в файловой системе FAT32) можно разделить образ диска на несколько частей (смотрите также split(1)):

    # dd if=/dev/sda conv=sync,noerror bs=64K | gzip -c | split -a3 -b2G - /путь/к/копии.img.gz

Если не хватает свободного места на локальном диске, можно отправить образ через ssh:

    # dd if=/dev/sda conv=sync,noerror bs=64K | gzip -c | ssh user@local dd of=копия.img.gz

Наконец, сохраните дополнительную информацию о геометрии диска, необходимую для интерпретации таблицы разделов, хранящейся в образе. Наиболее важной из них является размер цилиндра.

    # fdisk -l /dev/sda > /путь/к/list_fdisk.info

Примечание: Вы можете использовать размер блока (`bs=`), равный объёму кэша на диске, с которого выполняется копирование. Например, `bs=8192K` подходит для кэша 8 МиБ. Упомянутые в этой статье 64 КиБ лучше, чем стандартные `bs=512` байт, но при большем `bs=` копирование будет ещё быстрее.
Совет: gzip использует всего одно ядро процессора для сжатия, из-за чего скорость копирования может оказаться сильно меньше, чем скорость записи на современных накопителях. Чтобы использовать многоядерное сжатие и быстрее создать образ диска, можно, например, установить пакет pigz и просто заменить команду `gzip -c` на `pigz -c`. Для больших дисков это может сэкономить часы. Также можно попробовать другие алгоритмы сжатия, например zstd.

### Восстановление системы

Чтобы восстановиться из такой резервной копии:

    # gunzip -c /путь/к/копии.img.gz | dd of=/dev/sda

Если образ был разделён на несколько частей командой split, используйте другую команду (обратите внимание на звёздочку):

    # cat /путь/к/копии.img.gz* | gunzip -c | dd of=/dev/sda

## Патчинг бинарных файлов

Если нужно заменить заменить три байта `FF C0 14` по смещению `0x123AB`, это можно сделать с помощью такой команды:

    # printf '\xff\xc0\x14' | dd seek=$((0x123AB)) conv=notrunc bs=1 of=/путь/к/файлу

## Резервное копирование и восстановление MBR

Перед внесением изменений на диск можно создать резервную копию таблицы разделов и схемы разделов диска. Также можно использовать резервную копию для копирования одной и той же схемы разделов на несколько дисков.

MBR хранится в первых 512 байтах диска. Она состоит из 4 частей:

1. Первые 440 байт содержат загрузочный код (загрузчик).
2. Следующие 6 байт содержат сигнатуру диска.
3. Следующие 64 байта содержат таблицу разделов (4 записи по 16 байт каждая, по одной записи на каждый основной раздел).
4. Последние 2 байта содержат сигнатуру загрузки.

Сохранение MBR в `mbr_file.img`:

    # dd if=/dev/sdX of=/путь/к/mbr_file.img bs=512 count=1

Также можно извлечь MBR из полного образа диска dd:

    # dd if=/путь/к/образу.img of=/путь/к/mbr_file.img bs=512 count=1

Для восстановления (будьте осторожны, это уничтожит существующую таблицу разделов, а вместе с ней и доступ ко всем данным на диске):

    # dd if=/путь/к/mbr_file.img of=/dev/sdX bs=512 count=1

Важно: Восстановление MBR с несоответствующей таблицей разделов сделает ваши данные нечитаемыми и практически невозможными для восстановления. Если вам просто нужно переустановить загрузчик, смотрите соответствующие страницы, поскольку они также используют DOS compatibility region: GRUB (Русский) или Syslinux (Русский).

Если вы хотите восстановить только загрузчик, но не информацию о разделах, просто восстановите первые 440 байт MBR:

    # dd if=/путь/к/mbr_file.img of=/dev/sdX bs=440 count=1

Восстановление только таблицы разделов без затрагивания загрузчика и сигнатуры:

    # dd if=/путь/к/mbr_file.img of=/dev/sdX bs=1 skip=446 count=64

### Удаление загрузчика

Чтобы стереть загрузочный код MBR (может быть полезно, если вам нужно сделать полную переустановку другой операционной системы), можно обнулить первые 440 байт:

    # dd if=/dev/zero of=/dev/sdX bs=440 count=1

## Решение проблем

### Partial read

Файлы, созданные с помощью dd, могут иметь меньший размер, чем запрошено, если полный входной блок недоступен и системный вызов read(2) завершается раньше времени. Это может произойти при чтении из pipe(7) или при чтении с `/dev/random` и недостаточной энтропии[3], или с `/dev/urandom` при чтении более 32 МиБ[4].

Возможно, но не гарантировано, что dd предупредит вас об этой проблеме:

    dd: warning: partial read (X bytes); suggest iflag=fullblock

Решается это так, как и предлагает предупреждение: добавлением `iflag=fullblock` к команде dd:

    $ dd if=/dev/random of=bigsecret.img bs=1K count=1 iflag=fullblock
    $ dd if=/dev/urandom of=bigsecret.img bs=40M count=1 iflag=fullblock

Примечание: Крайне желательно всегда использовать `iflag=fullblock` при чтении из `/dev/random` или `/dev/urandom`.

Для `/dev/urandom` также можно задать большее число копируемых блоков:

    $ dd if=/dev/urandom of=bigsecret.img bs=1M count=40

При чтении из pipe альтернативой для для `iflag=fullblock` может быть прописывние для `bs` значения `PIPE_BUF`, которое определено в `/usr/include/linux/limits.h` [5]. Например:

    $ cat input.img | dd of=output.img bs=4k count=100

Category:

- Commands (Русский)