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

tl;dr: Команда dd умеет читать и записывать диски, но не обладает какими-либо "низкоуровневыми возможностями работы с вводом-выводом", делающими её использование более предпочтительным в сравнении с другими утилитами командной строки. Подобно cat, вы должны использовать её там, где это имеет смысл, например, чтобы воспользоваться широким спектром опций, а не стараться из страха и суеверия убеждать себя, что все относящиеся к диску команды начинаются и заканчиваются dd.

Если вы когда-либо пользовались dd, то, вероятно, использовали её чтобы прочитать или записать образ диска:

# Запись myfile.iso на USB-накопитель
dd if=myfile.iso of=/dev/sdb bs=1M

Использование dd в данной ситуации настолько распространено, что она могла бы быть провозглашена волшебным привратником raw-устройств. Как прочитать с raw-устройства? Используйте dd. Хотите записать на raw-устройство? Используйте dd.

Это убеждение добавляет ненужную сложность простым командам. Как объединить dd с gzip? Как использовать pv, если источник -- raw-устройство? Как использовать dd через ssh?

Люди придумывают остроумные способы вставить dd в начало и конец конвейеров.
dd if=/dev/sda | gzip > image.gz, -- пишут они. -- dd if=/dev/sda | pv | dd of=/dev/sdb.

Использование dd в обоих случаях не является целесообразным. Это просто суеверное заклинание, направленное на защиту данных. Вы можете увидеть, насколько это глупо, заменив dd функционально эквивалентным cat: cat /dev/sda | pv | cat > /dev/sdb

Дело в том, что dd не является инструментом для записи на диск. Ни одна из букв "d" не означает “disk”, "drive" или "device". Она не поддерживает "низкоуровневое" чтение или запись. Она не имеет никакой особой власти над каким-либо устройством.

dd просто читает и пишет файлы.

В UNIX, как говорится, всё есть файл. Это включает в себя и raw-диски. Поскольку raw-диски -- это файлы и dd может быть использована для копирования файлов, dd применяется для копирования raw-дисков.

Но знаете ли вы что ещё может читать и писать файлы? Всё:

# Запись myfile.iso на USB-накопитель
cp myfile.iso /dev/sdb

# Копирование cdrom в .iso файл
cat /dev/cdrom > myfile.iso

# Создание сжатого образа gzip
gzip -9 < /dev/sdb > /tmp/myimage.gz

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

В конечном итоге dd может выполнять задачу даже хуже. По спецификации дефолтный размер блока -- 512 байт и он не должен был меняться десятилетиями. Сегодня такой крошечный размер по умолчанию привязывает его к CPU. Скрипт, в котором не указан размер блока, очень неэффективен. И любой скрипт, использующий актуальное оптимальное значение, может со временем постепенно устареть или оказаться устаревшим, если его откуда-то скопировали.

Между тем, cat может свободно выбирать размер буфера, более подходящий в современной системе, а его размер в GNU cat неуклонно рос с 512 байт в 1991 до 131072 байт в 2014 (Примечание переводчика: 262144 байт в 2024) году. src/ioblksize.h в исходном коде coreutils содержит тесты, поддерживающие этот выбор.

Однако всё это совсем не означает, что dd нужно категорически избегать! Причина, по которой люди стали использовать её в первую очередь, состоит в том, что dd делает именно то, что ей говорят: не больше и не меньше.

Если в алиасе указан параметр -a, cp может попытаться создать новое блочное устройство вместо копирования данных файла. Если использовать gzip без перенаправления, он может попытаться оказаться полезным и пропустит файл, являющийся простым и обычным. И никто из них не выведет обнадёживающий статус в процессе или после копирования.

У dd, между тем, есть единственная задача *: копировать данные с одного места в другое. Её не волнуют файлы, аттрибуты безопасности или удобство пользователя. dd не будет пытаться угадать ваши намерения, основываясь на наличии оконечных слешей или типов файлов.

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

Это вовсе не означает, что я считаю dd переоценённым! Au contraire! Это один из моих любимых инструментов Unix!

dd -- это швейцарский армейский нож для системных вызовов open, read, write и seek. Эта команда уникальна своей способностью выполнять seeks и reads определённой длины, что позволяет создавать целый мир shell-скриптов, которые не имеют никакого отношения к shell-скриптам. Хотите имитировать lseek+execve? Используйте dd! Хотите открыть файл с помощью O_SYNC? Используйте dd! Хотите прочитать группы трёхбайтных пикселей из файла PPM? Используйте dd!

Это гибкий, уникальный и полезный инструмент, и он мне нравится. Единственное, что меня смущает, так это что слишком часто этот замечательный инструмент низводят до уровня его самой общей и наименее интересной способности и неуместно хвалят за это: простое копирование файла от начала и до конца.


* На самом деле dd выполняет две задачи: преобразование и копирование. В посте на comp.unix.misc (ошибочно) утверждалось, что предполагаемое имя "cc" было занято компилятором C, так что буквы были смещены таким же образом, каким Window System в итоге получила название X. Но более вероятное объяснение дали здесь в обсуждении Paweł и Bruce (Примечание переводчика: речь про комментарии к оригинальному посту): название, синтаксис и назначение почти идентичны команде JCL "Dataset Definition", встречавшейся в мейнфреймах IBM 1960-х годов.

Комментарии (20)


  1. Naves
    01.09.2024 20:48
    +10

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

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

    А теперь по теме.

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


    1. MzMz
      01.09.2024 20:48
      +7

      ... можно прочитать файл с убитого накопителя игнорируя блоки в которых есть ошибки


      1. ivankudryavtsev
        01.09.2024 20:48
        +3

        Лучше ddrescue, а не dd.


    1. MzMz
      01.09.2024 20:48
      +1

      ... потестировать производительность записи играясь с блоками разного размера


      1. ivankudryavtsev
        01.09.2024 20:48

        лучше fio, а не dd. Но dd тоже можно как первый шаг.


    1. dimkrayan
      01.09.2024 20:48
      +1

      ну, по дефолту (без специального ключа) оно использует кеш.
      А если знать об этой проблеме - не сложно и вручную выполнить sync после выполнения нужной команды.

      Но не подумайте, что я согласен с автором статьи.


      1. 13werwolf13
        01.09.2024 20:48

        всё же есть небольшая разница, при `oflag=direct` писаться будет игнорируя кеш и стараясь занять устройство настолько на сколько это возможно. в случае же отсутствие флага и выполнения sync после dd вы можете открыть iotop/iostat и убедиться что 9 стоматологов из 10 занимают устройство процентов на 30 (конечно же цифра не точная, просто пример) неторопливо сбрасывая кеш в промежутках между более важными делами.

        к тому же если в системе не одна флешка куда пользователь записывал iso а 100500 устройств с 100500 файлух то sync можно ждать очень долго не зная точно а чего мы собственно ждём флешку или какой нибудь оверзанятый рейд на 100 дисков 5600rpm.


  1. Sly_tom_cat
    01.09.2024 20:48
    +1

    А cp умет читать игнорируя ошибки?
    Ну да, я допустим буквально вчера на флешку образ через `cp ... ; sync` залил. Но только потому, что это гораздо проще набрать, чем все эти параметры dd (которые после долгого срока "непользования" этой командой еще и вспомнить надо или ман полистать). Но вот вытаскивая данные с полуживого диска опция игнора ошибок dd мне сильно помогла однажды.


  1. Sap_ru
    01.09.2024 20:48
    +5

    А cat умеет работать с буферами большого размера? А с асинхронным чтением/записью? А то у вас там пример с bs=1M, а у cat какой буфер? 64k?
    А чтобы буфер 10Gb и аcихнонное direct чтение в него, cat умеет? А то бывает нужно, если хочется всё быстро прочитать, а потом медленно писать, и при этом не забивать кэш системы.
    А прямое чтение и запись в обход кэшей cat умеет? Ну, чтобы точно на устройство, а не в буфера? А так, чтобы чтение через кэш, а запись direct?
    А sync в конце записи cat умеет?
    А так, чтобы вообще без барьеров синхронизации cat умеет писать?

    Более того, зачем вы этот gzip вообще используете?! У вас есть много лишнего времени? То есть МНОГО лишнего времени - в восемь раз больше, чем реально нужно? Или у вас есть много лишнего места - раза в два больше, чем нужно? Есть же pigz и pixz, которые намного быстрее и лучше жмут, что может быть критически важно для сжатия образов! pixz круто уделает ваш "gzip -9" одновременно и по скорости и степени сжатия!

    P.S. Да, я понимаю, что перевод, но это такая лютая дичь, что она банально вредна для неокрепших умов. Неокрепшим умам нужно бы узнать про dd, про pipes и про pixz/pigz, а не забивать шурупы доски деревянным молоком.


    1. Melirius
      01.09.2024 20:48
      +2

      А есть какая книжка на тему современная?


      1. ivankudryavtsev
        01.09.2024 20:48
        +2

        man dd - самая современная книжка. Или вы про Advanced bash scripting guide спрашиваете?


  1. rogoz
    01.09.2024 20:48
    +2

    cp и cat не умеют в, например, oflag=dsync или oflag=direct.


    1. Wesha
      01.09.2024 20:48

      А ещё они не умеют в status=progress или в SIGINFO.


      1. CrazyOpossum
        01.09.2024 20:48
        +1

        Для сложных вещей отлично rsync подходит.


  1. A1EF Автор
    01.09.2024 20:48
    +3

    Видимо, чрезмерная провокационность заголовка привела к тому, что комментаторы просмотрели статью по диагонали и сразу накидали возражений вида "автор неправ и вот почему" :)

    Что ж, попробую пояснить почему мне статья показалась интересной и стоящей перевода. Во-первых, на самом деле автор не утверждает, что dd не нужен, а cat , pv и cp полностью его заменяют. Дело лишь в том, что львиная доля статей в Интернете с использованием dd -- это что-то вида:

    Запишем образ на флешку: dd if=image.iso of=/dev/sdb

    Вот как раз это -- на мой взгляд -- и вредит "неокрепшим умам", формируя уверенность, что только так и нужно всегда делать, только dd и может записать образ на блочное устройство (или наоборот). А ведь это совсем не так!

    Во-вторых, автор знает про флаги dd , просто в данной статье демифилогизирует её как саму по себе некую "волшебную утилиту". Поэтому странно видеть нападки на те тезисы, которые вовсе и не утверждались. Тем более, что тут всегда можно углубиться в поисках более оптимальных вариантов выполнения определённых действий: так, субъективно, с убитого накопителя лучше читать силами ddrescue , тестировать производительность -- fio , красивый прогресс-бар может рисовать pv, а потребность использовать буферы большого размера, обход кэша и вызов sync уже явно выходят за общеупотребительный универсальный вариант использования. Ну а архиваторы и вовсе не тема данной статьи.


    1. unreal_undead2
      01.09.2024 20:48
      +2

      А ведь это совсем не так!

      Угу

      Вы можете увидеть, насколько это глупо, заменив dd функционально эквивалентным catcat /dev/sda | pv | cat > /dev/sdb

      Это удобнее, чем dd ?


      1. A1EF Автор
        01.09.2024 20:48

        Удобство - вопрос субъективный, а так-то тут и pv вместо cat можно было сразу вписать, и буковок чуть меньше набирать :)


      1. eps
        01.09.2024 20:48
        +2

        Давайте заменим useless dd на useless use of cat (Award)

        The purpose of cat is to concatenate (or "catenate") files. If it's only one file, concatenating it with nothing at all is a waste of time, and costs you a process.


    1. Naves
      01.09.2024 20:48
      +1

      Проблема этой статьи именно в том, что она не объясняет ничего, а имеет только заголовок.

      Немного затрагивает проблематику множества противоречивых инструкций, успешно пополняя это множество.

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

      В общем и целом, автор троль, успешно набросил на вентилятор.


  1. rcl
    01.09.2024 20:48

    Радость познания и не более. Смысла переводить чужие радости на русский нет.