Материал просмотрен 3,129 раз(а)

В UNIX-подобных системах есть одна интересная команда, которая занимается побайтным копированием чего-то из одного места в другое.

На первый взгляд кажется, что это сущий пустяк, но если разобрать работу с этой утилитой на практике – открывается масса возможностей её применения.

Имя этой утилите – dd.

Какие операции возможно производить с её помощью:

  • Создание дампа данных с различных носителей;
  • Резервное копирование и восстановление MBR;
  • Анализ файловой системы, индексных дескрипторов и поиск удалённых файлов;
  • Зеркалирование носителей информации;
  • Создание файлов произвольного размера и содержания;
  • Запись в файл/чтение из файла по произвольному смещению и произвольным размером;
  • …многое другое, перечень задач ограничивается лишь извращённой фантазией линуксоидов;

Небольшой пример, демонстрирующий общие принципы работы с утилитой.

Пример 1. Создание произвольного файла нужного размера.

# dd if=/dev/urandom of=my.rnd bs=1 count=30

Разберём основные параметры:

  • if (input file) – источник, откуда копируем данные;
  • of (output file) – получатель, куда копируем;
  • bs (block size) – размер блока, записывается в байтах. Можно использовать суффиксы K, M, а так же использовать операции умножения, об этом ниже.
  • count – количество таких блоков.

Таким образом, вышеприведённая команда копирует 30 блоков размером в 1 байт из устройства случайных значений в файл my.rnd

Кстати, рекомендую дампы перенаправлять на вход утилиты hexdump с ключом -C.

Пример 2. Работа с блочными данными. Образ CD-ROM

Первым делом необходимо смонтировать диск. Для этого я воспользуюсь утилитой mount_cd9660, которая находится в каталоге /sbin. Она понимает файловую систему компакт-диска, но вы без проблем можете использовать обычный mount.

# /sbin/mount_cd9660 -e /dev/acd0t01 /cdrom

Монтирую устройство /dev/acd0t01 в каталог /cdrom, имя устройства я узнал выполнив поиск:

# ls -la /dev/*cd*

Итак, устройство смонтировали, прочитаем один стандартный блок файловой системы ISO cd9660. Напоминаю, если кто не знает, что стандартный размер блока равен 2048 байт.

# dd if=/cdrom of=/root/TEST/cd2k.img bs=1Kx2 count=1

Прошу обратить внимание, что в параметре bs я использовал сразу две фишки. Суффикс К = 1024 и знак х – умножение. Т.е. запись 1Kx2 (1Кб * 2) эквивалентна 1024×2 или 2048. Просто иногда удобно указывать суффиксы, иногда – умножать, а иногда – прямым значением. Гибкость – залог успеха, верно?

Так же прошу обратить внимание на вывод утилиты.

1+0 records in

1+0 records out

Это значит, что скопирована 1 полная запись на источнике и записана одна полная запись на получатель. Если было бы 3+1, то это означало бы, что взято 3 целых блока и ещё 1 неполный. Такое могло быть, если бы я не указал count, а размер файла источника был бы равен, например, 6200 байт. Трижды по 2048 (это будет 6144 байт) и остальные 56 байт – это было бы то, что после +. Ну, надеюсь не запутал. То есть целые и нецелые блоки данных. Вот что важно.

Вот такой вот важный параметр bs. К слову, существуют ещё три парметра размера блока:

  • ibs – размер входного блока;
  • obs – размер выходного блока;
  • cbs – размер буфера преобразования, о нём потом.

Но если указан размер bs, то все остальные размеры блоков игнорируются. Такой вот параметр-“папа”.

Пример 3. Сохранение копии MBR с диска.

Как известно, MBR находится в первых 512 байтах первого сектора

# dd if=/dev/ad0s1 bs=512 count=1 | hexdump -C | less

Думаю, параметры тут не вызывают вопросов. 512 байт с 1-го сектора, перенаправление в hexdump и постраничный вывод. Сохранённый mbr лучше запрятать подальше, хранится там важная вещь – загрузчик и таблица разделов. Кстати, увидели в конце загрузочной записи сигнатуру 55 AA? Это особый знак, который сигнализирует компьютеру о таблице разделов.

Если нам нужна не вся MBR, а только лишь загрузочный код, который занимает 446 байт, то нам пригодится новый параметр.

Помимо этого существуют параметры пропуска N-ого количества блоков от начала файла (входного или выходного).

  • seek=n – пропускает n блоков (размера bs) в выходном файле (of) прежде чем начинает туда записывать.
  • skip=n – пропускает n блоков (размером bs) во входном файле (if) прежде чем начать оттуда считывать.

Варьируя эти параметры можно добиться ошеломляющих результатов.

Пример 4. Запись произвольной части произвольного файла.

На мой взгляд, очень показательный пример. Имеем текстовый файл. Выполняем команду:

# echo "ALL " | dd of=out.txt bs=1 seek=6 conv=notrunc

То есть подаём строку ALL на вход утилиты dd, которая пишет на выход в файл out.txt начиная с 6-го блока (размером в 1 байт) и остаток файла не обрезает (conv=notrunc), с параметрами конвертации ознакомьтесь из man dd, особенно рекомендую noerror.

Засим откланиваюсь! Всего доброго! Надеюсь, было прикольно.