Наши партнеры

UnixForum






Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

На главную -> MyLDP -> Тематический каталог -> Работа в консоли Linux

dd: Команда, которая не похожа на другие

Автор: Алексей Дмитриев
Дата: ноябрь 2008

Преобразования или конвертации

В первых строках любого мана dd говорится: "Команда dd копирует указанный входной файл в указанный выходной, совершая при необходимости преобразования." Причем совершаются эти преобразования одновременно с копированием, как говорят по-английски "на лету".

Одной из первоначальных задач команды dd была работа с 1/2" ленточными накопителями, которые применялись для переноса данных с одной машины на другую, а также для запуска и установки ОС Юникс на машинах PDP/11. Те времена прошли, а 9-дорожечный формат остался. И остался до тонкостей разработанный синтаксис этих преобразований.

Как мы уже знаем, ведает конвертациями операнд conv.

conv=значение В некоторых манах значение называют фильтром. Список этих значений-фильтров сильно варьирует от системы к системе. Тут вообще уместно сделать небольшое отступление для тех, кто захочет досконально разобраться с командой dd.

Существует несколько реализаций программы dd. В Линукс системах чаще всего встречается GNU Coreutils dd. В BSD своя реализация, в Solaris своя. Я имею сильное подозрение, что все они похожи как близнецы братья, только маны разные. Самые толковые, подробные и запутанные маны от Solaris, за ними идут BSD, а самые коротенькие от GNU. Похоже, что они не описывают и половины способностей программы. Я приведу здесь выдержки из нескольких манов, а в приложении [2] дам перевод самого длинного.

Итак значения или фильтры для операнда conv=значение:

  • ascii Преобразует (конвертирует) кодировку EBCDIC (Extended Binary Coded Decimal Interchange Code) в ASCII.
  • ebcdic Преобразует кодировку ASCII в EBCDIC. При преобразовании записей ASCII фиксированной длины, не разделенных символами новой строки, необходимо организовать конвейер и предварительно обрабатывать данные командой dd conv=unblock.
  • ibm Немного другое преобразование кодировки ASCII в EBCDIC.
  • Внимание! Значения ascii, ebcdic и ibm - взаимоисключающие.

Сейчас нам придется прервать список значений операнда conv, чтобы вспомнить о четвертом операнде размера блока. Когда мы обсуждали эти операнды (bs, ibs, obs и cbs), то ничего не сказали про операнд:

cbs=n(байт) Определяет размер буфера (блока) преобразования. Задает размер блока преобразования (n байтов, по умолчанию - 0) для операндов block и unblock. Если операнд cbs= не указан или задает значение 0, использование операндов block и unblock дает неопределенные результаты.

Познакомившись с операндом cbs, мы можем продолжать список значений-фильтров операнда conv:

  • block Рассматривает входной файл как последовательность записей переменной длины, завершаемых символами новой строки или символом конца файла (EOF), независимо от размера входного блока. Каждая запись преобразуется в запись фиксированной длины, задаваемой размером блока преобразования. Все символы новой строки из входной строки удаляются; к строкам при необходимости добавляются пробелы, чтобы заполнить блок. Строки, длина которых превышает размер блока преобразования, усекаются до этого размера; утилита сообщает о количестве усеченных строк.
  • unblock Преобразует записи фиксированной длины в записи переменной длины. Читает количество байтов, равное размеру блока преобразования (или оставшиеся байты входного файла, если их меньше, чем байтов в блоке преобразования), удаляет все хвостовые пробелы и добавляет символ новой строки.
  • Внимание! Значения block и unblock - взаимоисключающие.

Чтобы показать, зачем нужны все эти блоки-анблоки, приведу конкретный пример. Повторюсь, что поначалу задача команды dd была работа с 1/2" ленточными накопителями, которые применялись для переноса данных с одной машины на другую. Те времена прошли, а 9-дорожечный формат остался. И команда dd не имеет себе равных в доступе к освященным веками 1/2" девятидорожечным ленточным накопителям. На современных SCSI ленточных устройствах разделение на блоки и распаковка блоков больше не обязательны, так как устройства читают и записывают блоками данных по 512 байт.

Тем не менее, 9-дорожечный 1/2" ленточный формат позволяет создавать блоки различной длины, поэтому его невозможно прочесть при помощи команды cp. Команда dd позволяет настраивать размер входных и выходных блоков, и даже может считывать блоки варьируемой длины, если установить размер входного буфера заведомо больший, чем самый большой блок на ленте. Короткие блоки считываются, и dd весело и без жалоб копирует их в выходной файл, просто подсчитывая количество полных и неполных блоков.

Есть еще EBCDIC наборы данных, перенесенные с таких операционных систем как MVS, почти всегда они представлены образами 80-колонных перфокарт Холлерита! Команда dd без проблем конвертирует их в ASCII.

Пример 11. Конвертация EBCDIC

Конвертация EBCDIC 80-значных фиксированной длины записей в записи ASCII переменной длины с подставлением символов новых строк:

# dd bs=10240 cbs=80 conv=ascii,unblock if=/dev/st0 of=ascii.out
40+0 records in
38+1 records out

Фиксированная длина записи указана как параметр cbs=80; входные и выходные блоки установлены параметром bs=10240. Конвертация EBCDIC-в-ASCII и фиксированная-в-переменную длины записей включены параметрами conv=ascii,unblock.

Получив некоторое представление о значениях block и unblock, давайте вернемся к продолжению списка значений-фильтров операнда conv:

  • lcase Преобразует все символы верхнего регистра, в соответствии со значением LC_CTYPE, в нижний регистр. Символы, для которых преобразование в локали не задано, не изменяются.
  • ucase Сами понимаете, наоборот
  • Внимание! Значения lcase и ucase - взаимоисключающие.

Пример 12. Преобразование верхнего регистра в нижний

Создайте текстовой файл uppercase.txt следующего содержания: "THЕSЕ LETTERS ARE UPPERCASE" (что по-нашему значит: "Все эти буквы в верхнем регистре"). Затем наберите команду:

$ dd if=uppercase.txt conv=lcase
these letters are uppercase

Поскольку мы не указали выходной файл (of), то получили преобразование на стандартный выход. Интересно, что с русскими буквами конвертация не осуществляется, видимо что-то нужно изменить в переменной окружения LC_CTYPE.

Вернемся к списку значений операнда conv:

  • swab Уже знакомое нам значение. Переставляет байты в каждой входной паре. Если в текущей входной записи нечетное количество байтов, последний байт игнорируется.
  • noerror Не останавливать обработку в случае ошибки чтения. При возникновении ошибки чтения в стандартный поток ошибок выдается диагностическое сообщение, а затем - текущий входной и выходной блок в том же формате, что и при завершении работы. Если задано преобразование sync, недостающие входные данные будут заменены нулевыми байтами; в противном случае, сбойный входной блок просто не попадает в выходной файл.

    Это чрезвычайно важное значение. Ведь делая резервные копии больших файлов, скажем жестких дисков, вся работа пошла бы насмарку из-за крохотной ошибки в одном байте.

  • sync Дополнять каждый входной блок до размера буфера, задаваемого операндом ibs=, добавляя нулевые байты. (Если указан также операнд block или unblock, добавляются пробелы, а не нулевые байты.)

Сделаем копию жесткого диска, используя два последних значения операнда conv,

Пример 13. Создание резервной копии жесткого диска прямо на другой диск:

# dd if=/dev/hda of=/dev/sda conv=noerror,sync bs=4k

Выбор размера блока не случаен: при маленьких блоках процесс копирования затянется, Можно задать большие блоки, но тогда в случае ошибок, оставшиеся после ошибки части блока будут заполнены нулями. Поэтому чем больше блоки, тем больше информации вы потеряете.

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

Пример 14. Создание резервного образа жесткого диска:

# dd if=/dev/hda | gzip > /mnt/hdb1/system_drive_backup.img.gz

Команда dd создает образ первого жесткого диска и по конвейеру (не забудьте про стандартный вывод по умолчанию) передает программе сжатия gzip. Сжатый образ затем помещается в файл system_drive_backup.img.gz, находящийся на другом диске (hdb1). Чтобы произвести обратное действие:

 
# gzip -dc /mnt/hdb1/system_drive_backup.img.gz | dd of=/dev/hda

Программа gzip распаковывает (опция -d) файл, передает результат на стандартный выход (опция -c), по конвейеру данные поступают программе dd, которая записывает выходной файл (устройство /dev/hda).

Незаметно мы рассмотрели почти все значения (фильтры) операнда conv. Тут и ману конец. Но сначала несколько правил относящихся к взаимодействию операндов.

Правило 1. Все операнды обрабатываются до начала чтения входных данных. В практическом смысле это значит, что можно писать операнды в любом порядке - результат будет один. Скажем команда:

# dd if=/dev/hda of=/dev/sda conv=noerror,sync bs=4k

равносильна команде

# dd bs=4k conv=noerror,sync if=/dev/hda of=/dev/sda

Правило 2. Если операнды (кроме conv=) указаны более одного раза, будет использоваться значение из последней пары операнд=значение.

Еще примеры возможностей команды dd

Пример 15. Уничтожение всех данных в разделе hdc2, размером 1Гб:

Чтобы было невозможно восстановить содержимое этого раздела, заполним его нулями от первого до последнего байта.

# dd if=/dev/zero of=/dev/hdc2 bs=1M
dd: запись `/dev/hdc2': No space left on device
957+0 записей считано
956+0 записей написано
скопировано 1003484160 байт (1,0 GB), 44,7713 секунд, 22,4 MB/s

А можно псевдослучайными байтами:

# dd if=/dev/urandom of=/dev/hdc2 bs=1M
dd: запись `/dev/hdc2': No space left on device
957+0 записей считано
956+0 записей написано
скопировано 1003484160 байт (1,0 GB), 1050,83 секунд, 955 kB/s

Давайте проверим, что получилось. Возьмем на вскидку 1001 сектор раздела hdc2, который мы только что заполнили псевдослучайными байтами:

# dd if=/dev/hdc2 bs=512 count=1 skip=1000

???:?+K▒^??8???/-O?L*lJ?N`????????_
?7$?.pXi(\kN]c??6@lJ2IM]Z?9iAVlm?6?wCm?;s???r?2\?&Sd>???!n??!????P???9!s-{?    0??-uK???H?a>?F[?S[
            ???▒w?JP(wt~W1????D? }E?cF>|?8{9 Q?t%7AnFtu
j?J??L?
xv?'??_bs??TP   }Du?
1+0 записей считано
1+0 записей написано
скопировано 512 байт (512 B), 0,0114453 секунд, 44,7

Действительно, ахинея! Справедливости ради нужно заметить, что заполнение нулями при прочих равных условиях занимает на порядок меньше времени.

Кстати, таким же способом можно прочесть любой сектор, или группу секторов любого носителя.

Особые случаи применения команды dd

Команда dd применяется в судебной и криминалистической практике. Самое очевидное применение - снятие точных (побайтовых) копий с жестких дисков подозреваемого. Работать с ними удобнее (не нужно подключать диски физически), да и места займет немного.

# dd if=/dev/hda of=/dev/case10img1

Другой случай. В руках криминалистов оказалась магнитная лента, подлежащая исследованию. Но неизвестен размер блока на этой пленке, а знание правильного размера многократно ускорит процесс прочтения. Можно попытаться определить размер блока при помощи команды dd:

# dd if=/dev/st0 ibs=128 of=/dev/case10img1 obs=1 count=1

задав несуразный размер входного блока (ibs=128), мы провоцируем программу выдать сообщение об ошибке, в котором будет указан истинный размер блока.

Еще одно применение команды dd состоит в возможности порезать большой объем данных (жесткий диск) на кусочки, удобные для записи на другие носители (например DVD):

# dd if=/dev/st0 bs=1M count=4000 of=/dev/case10img1

# dd if=/dev/st0 bs=1M count=4000 skip=4000 of=/dev/case10img2

# dd if=/dev/st0 bs=1M count=4000 skip=8000 of=/dev/case10img3

# dd if=/dev/st0 bs=1M count=4000 skip=12000 of=/dev/case10img4

И так далее...

Команда dd и MS Windows

Существует реализация команды dd для Win32. Читайте статью Команда dd для Windows

К читателям

Уважаемые коллеги, если вы знаете, или прочитали про другие возможности применения команды dd, не сочтите за труд написать мне. Только пожалуйста, не ограничивайтесь одной командной строкой, а, по возможности, объясните что там к чему. Мой e-mail: yakwiat@yandex.ru.
Назад, страницы 1, 2, 3. Вперед, страница 4.


Средняя оценка 5 при 1 голосовавших