дд против кошки - дд еще актуален в наши дни?

122

Я недавно понял, что мы можем использовать catстолько, сколько dd, и это на самом деле быстрее, чемdd

Я знаю, что это ddбыло полезно при работе с лентами, где размер блока действительно имел значение в правильности, а не только в производительности. В наши дни, однако, бывают ситуации, когда ddможно что-то сделать, а что catнет? (Здесь я бы посчитал разницу в производительности менее 20% несущественной.)

Конкретные примеры были бы хороши!

kizzx2
источник
1
Посмотрите этот ТАК вопрос для одного конкретного примера.
Camh

Ответы:

156

По внешнему виду, ddэто инструмент из операционной системы IBM, который сохранил свой внешний вид (передачу параметров), который выполняет некоторые очень редко используемые функции (такие как преобразования EBCDIC в ASCII или обращение к порядку байтов ... в настоящее время это не является обычной потребностью).

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

Я думаю, что некоторые из ddпараметров полезны при работе с лентами, где чтение действительно выполняется в блоках (драйверы ленты не скрывают блоки на носителе, как это делают драйверы дисков). Но я не знаю специфики.

Единственное, что ddможет сделать то, что не может (легко) сделать любой другой инструмент POSIX, - это взять первые N байтов потока. Многие системы могут сделать это head -c 42, но head -c, хотя и распространены, не в POSIX (и не доступны сегодня, например, на OpenBSD). ( tail -cэто POSIX.) Кроме того, даже там, где он head -cсуществует, он может считывать слишком много байтов из источника (поскольку он использует внутреннюю буферизацию stdio), что является проблемой, если вы читаете из специального файла, в котором только чтение имеет эффект. (Текущие значения GNU coreutils считывают точное количество head -c, но FreeBSD и NetBSD используют stdio.)

В более общем смысле, ddпредоставляет интерфейс для базового файлового API, который является уникальным среди инструментов Unix: только ddможет перезаписать или усечь файл в любой точке или выполнить поиск в файле. (Это ddуникальная способность, и она очень большая; как ни странно, ddлучше всего известны вещи, которые могут делать другие инструменты.)

  • Большинство инструментов Unix перезаписывают свой выходной файл, то есть стирают его содержимое и начинают его заново. Это то, что происходит, когда вы используете >перенаправление в оболочке.
  • Вы можете добавлять содержимое файла с помощью >>перенаправления в оболочке или с помощью tee -a.
  • Если вы хотите сократить файл, удалив все данные после определенной точки , это поддерживается базовым ядром и C API через truncateфункцию, но не предоставляется никаким инструментом командной строки, кромеdd :

    dd if=/dev/null of=/file/to/truncate seek=1 bs=123456  # truncate file to 123456 bytes
    
  • Если вы хотите перезаписать данные в середине файла, опять же, это возможно в API-интерфейсе underyling, открыв файл для записи без усечения (и вызывая lseekдля перемещения в нужную позицию при необходимости), но только ddможет открыть файл без усечение или добавление, или поиск из оболочки ( более сложный пример ).

    # zero out the second kB block in the file (i.e. bytes 1024 to 2047)
    dd if=/dev/zero of=/path/to/file bs=1024 seek=1 count=1 conv=notrunc
    

Итак ... Как системный инструмент, ddв значительной степени бесполезен. Как инструмент обработки текста (или двоичного файла), он весьма ценен!

жилль
источник
Принято, потому что я думаю, что это объясняет суть других ответов ( truncи seekпригодность для использования из dd).
kizzx2
2
Еще одно специальное использование: ddможет считывать двоичные данные из дескрипторов файлов без возможности поиска без потенциального уничтожения непрочитанных данных из-за буферизации stdio. Смотрите здесь для примера: etalabs.net/sh_tricks.html
R ..
2
@R ..: Да. В GNU coreutils 6.10 head -c Nзвонит readи никогда не выходит за пределы N. В NetBSD 5.1 head -cзвонки getc. В FreeBSD 7.4 head -cзвонки fread.
Жиль
1
Coreutils ddтакже предоставляет O_DIRECT (и т. Д.) Для сценариев оболочки, которые, я думаю, также уникальны.
Дероберт
1
Coreutils truncateпозволяет обрезать или расширять файлы, что исключает другое использование dd.
dcoles
22

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

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

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

* Как отметил Жиль в комментариях, его можно комбинировать catс другими инструментами, чтобы изолировать части чего-либо, но при catэтом он действует на весь объект.

Калеб
источник
5
ddна самом деле не имеет ничего общего с низкоуровневыми устройствами, он нуждается в записи, /devкак и другие. Вы можете скопировать весь раздел с помощью catили его часть с помощью tail +c $(($start+1)) | head -c $count.
Жиль
16
Конечно. ;-) И когда я передаю образ диска объемом 1,6 ТБ, cat | head | tailчтобы извлечь последние несколько МБ, вращение диска высосет луну ближе к земле.
Калеб
2
@Gilles Извините, я действительно хотел признать, что мое использование термина «низкий уровень» было не очень хорошей дикцией, хотя я имел в виду данные на устройствах, а не на устройствах. Возможно, «точно настроенная обработка данных» будет лучше, чем «обработка данных низкого уровня».
Калеб
21

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

dd if=/dev/zero of=sparse-file bs=1 count=1 seek=10GB

Это почти мгновенно и создает произвольный большой файл, который можно использовать, например, в качестве петлевого файла:

loop=`losetup --show -f sparse-file`
mkfs.ext4 $loop
mkdir myloop
mount $loop myloop

Приятно то, что изначально он использует только один блок дискового пространства, а затем увеличивается только по мере необходимости (форматирование ext4 файла 10 ГБ в моей системе занимает 291 МБ). Используйте, duчтобы увидеть, сколько фактически места на диске используется - lsсообщает только о максимальном размере файла.

Лауриц В. Таулов
источник
4
ls -lsпоказывает вам редкий размер.
JMTD
2
Ваша команда записывает бесполезный байт в файл. dd of=sparse-file bs=1 count=0 seek=10Gбудет эквивалентно truncate -s 10GB sparse-file. Достаточно запутанно, truncateи ddимеют совершенно противоположную интерпретацию GBпротив G...
frostschutz
5
@frostschutz: man ddговорит: MB =1000*1000, M =1024*1024и так далее. И man truncateговорит: MB 1000*1000, M 1024*1024так что разницы нет. Я использую ddи truncateиз GNU coreutils. Вы тоже должны это сделать! :-)
Эрик
@erik: Спасибо за исправление. Если это не изменилось недавно, я, должно быть, каким-то образом перепутал это с чем-то другим.
frostschutz
10

Переопределение определенных сегментов жесткого диска чем-то - типичный пример. Например, вы можете удалить MBR с помощью этой команды:

dd if=/dev/zero of=/dev/sda bs=446 count=1

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

dd if=/dev/zero of=10mb.file bs=1024k count=10
XQYZ
источник
Кроме того, эта вторая команда - самый быстрый из известных мне способов использования 10 МБ
Кевин М
3
@ Кевин: Быстрее, чем head -c? Пожалуйста, поделитесь ориентиром !
Жиль
9

ddочень полезно для резервного копирования загрузочного сектора жесткого диска или другого устройства хранения ( dd if=/dev/sda of=boot_sector.bin bs=512 count=1), а затем перезаписывает его ( dd if=boot_sector.bin of=/dev/sda). Это также полезно для резервного копирования заголовков зашифрованных томов.

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

LawrenceC
источник
5

У меня недавно была причина клонировать несколько разделов размером в несколько сотен гигабайт впервые в моей истории linuxing (ср. cp -arИли rsyncкоторые хорошо мне служили много раз). Конечно, я обратился к dd, потому что все знают, что это то, что вы используете ... и был потрясен производительностью. Вскоре меня немного погуглило ddrescue, что я уже использовал несколько раз и работает великолепно (намного быстрее, чем dd).

timday
источник
1
ddrescueотлично, особенно для получения данных с неисправных дисков.
ryenus
5

Вот несколько трюков, которые я придумал за эти годы.

Вырежьте и вставьте в недружелюбный tty или неинтерактивный режим bash

Если вы находитесь в ситуации, когда EOF / ^ D / ^ F не обнаружен, вы можете использовать dd для передачи текстовых файлов на хост. Так как он остановит чтение после указанного количества байтов автоматически.

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

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

dd of=textfile.txt bs=1 count=<size_of_data_in_paste_buffer>

Очень крутой трюк в том, что во время работы dd, если вы отправите ему сигнал USR1, он выдаст свое текущее состояние (считанные байты, байты в секунду ...)

Универсальный фильтр состояния пропускной способности

Я написал это, чтобы действовать как чистый фильтр прогресса bash для любой программы, которая генерирует данные через стандартный вывод. (Примечание: практически все что угодно будет генерировать данные через stdout - для программ, которые этого не делают, вы можете обмануть, если они не будут раздражать вас, используя / dev / stdout в качестве имени файла. Но идея в основном заключается в том, что каждый раз, когда вы получаете X количество байтов, печатные хеш-метки (как в старой школе FTP, когда у вас включен хеш-режим)

(Примечание) Файл с прогрессом хромает, в основном это было доказательством концепции. Если бы я переделал это, я бы просто использовал переменную.

 dd bs=$BLKSZ of=${TMPFILE} 2>&1 \
                | grep --line-buffered -E '[[:digit:]]* bytes' \
                | awk '{ print $1 }' >> ${PROGRESS} &

 while [[ $(pidof dd) -gt 1 ]]; do

        # PROTIP: You can sleep partial seconds
        sleep .5

        # Force dd to update us on it's progress (which gets
        # redirected to $PROGRESS file.    
        pkill -USR1 dd
        local BYTES_THIS_CYCLE=$(tail -1 $PROGRESS)
        local XFER_BLKS=$(((BYTES_THIS_CYCLE-BYTES_LAST_CYCLE)/BLKSZ))

        if [ $XFER_BLKS -gt 0 ]; then
                printf "#%0.s" $(seq 0 $XFER_BLKS)
                BYTES_LAST_CYCLE=$BYTES_THIS_CYCLE
        fi
done

файлы фрагментов с использованием анонимных дескрипторов оболочки

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

generate_hash() {
    echo "yay!"
}

# Create a tar file, generate a hash, append it to the end
tar -cf log.tar /var/log/* 2>/dev/null
TARFILE_SIZE=$(stat -f "%z" log.tar)
SIGNATURE=$(generate_hash log.tar)
echo $SIGNATURE >>log.tar

# Then, later, extract without getting an error..

tar xvf <(dd if=$OLDPWD/log.tar bs=1 count=${TARFILE_SIZE})

Я считаю, что дд невероятно полезен. И это только три примера, которые я могу придумать не покладая рук.

synthesizerpatel
источник
4

Вы можете перенаправить некоторый выходной контент. Это особенно полезно, если вам нужно написать с помощью sudo:

echo some_content | sudo dd status=none of=output.txt

Кроме того, sudoэто эквивалентно:

echo some_content > output.txt

или к этому:

echo some_content | sudo tee output.txt > /dev/null
Алексей
источник
Хорошая точка зрения. Подробнее о перенаправлении stdout в файл, на который у вас нет разрешения на запись
Стефан Шазелас