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

<p>недавно я понял, что мы можем использовать <code>cat</code> столько же, сколько <code>dd</code>, и это <a href="https://unix.stackexchange.com/questions/9432/is-there-a-way-to-determine-the-optimal-value-for-the-bs-parameter-to-dd/9492#9492">на самом деле быстрее, чем <code>dd</code></a> </p><p>я знаю, что <code>dd</code> был полезен при работе с лентами, где размер блока действительно имел значение в правильности, а не только в производительности. в наши дни, однако, бывают ситуации, когда <code>dd</code> может сделать то, что <code>cat</code> не может? (здесь я бы посчитал разницу в производительности менее 20% несущественной.)</p><p>конкретные примеры были бы хорошими!</p>

<p>по внешнему виду <a href="http://en.wikipedia.org/wiki/dd\_%28unix%29"><code>dd</code></a> - это инструмент из операционной системы ibm, который сохранил свой внешний вид (передачу параметров), который выполняет некоторые очень редко используемые функции (например, ebcdic для ascii преобразования или обращение к порядку байтов ... в настоящее время это не является общей потребностью).</p><p>я <a href="https://unix.stackexchange.com/questions/11464/how-to-write-repeated-free-form-strings-to-a-file-as-fast-as-dd/11468#11468">раньше думал</a> что <code>dd</code> был быстрее для копирования больших блоков данных на тот же диск (из-за более эффективного использования буферизации), но это <a href="https://unix.stackexchange.com/questions/9432/is-there-a-way-to-determine-the-optimal-value-for-the-bs-parameter-to-dd/9492#9492">это не так</a> , по крайней мере в современных системах linux.</p><p>я думаю, что некоторые параметры <code>dd</code> полезны при работе с лентами, где чтение действительно выполняется в блоках (драйверы ленты не скрывают блоки на носителе, как это делают драйверы дисков). но я не знаю специфики.</p><p><code>dd</code> может сделать одну вещь, которую нельзя (легко) сделать с помощью любого другого инструмента posix, - <strong> взять первые n байтов </strong> поток. многие системы могут сделать это с помощью <code>head -c 42</code>, но <code>head -c</code>, хотя и часто встречается, отсутствует в posix (и сегодня недоступен, например, в openbsd). (<code>tail -c</code> - это posix.) кроме того, даже там, где существует <code>head -c</code>, он может прочитать слишком много байтов из источника (потому что он использует внутреннюю буферизацию stdio), что является проблемой, если вы ' повторное чтение из специального файла, где только чтение имеет эффект. (текущие gnu coreutils читают точное число с помощью <code>head -c</code>, но freebsd и netbsd используют stdio.)</p><p>в более общем смысле, <code>dd</code> предоставляет интерфейс к базовому файловому api, который является уникальным среди инструментов unix: только <code>dd</code> может <strong> перезаписывать или усекать </strong> файл <strong> в любой точке </strong> или <strong> поиск </strong> в файле. (это уникальная способность <code>dd</code>, и она очень большая; как ни странно, <code>dd</code> наиболее известна тем, что могут делать другие инструменты.)</p><ul> <li>большинство инструментов unix перезаписывают свой выходной файл, то есть стирают его содержимое и запускают его с нуля. это то, что происходит, когда вы используете перенаправление <code>></code> в командной консоли.</li> <li>вы можете добавить содержимое файла с помощью перенаправления <code>>></code> в командной консоли или с помощью <code>tee -a</code>.</li> <li> <p>если вы хотите сократить файл, удалив все данные <em> после определенного момента</em>, это поддерживается базовым ядром и c api через <a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/truncate.html"><code>truncate</code></a> функция, но не предоставляется никаким инструментом командной строки <a href="https://unix.stackexchange.com/questions/1279/how-can-i-edit-large-file/1305#1305">кроме <code>dd</code></a> :</p> <pre><code>dd if=/dev/null of=/file/to/truncate seek=1 bs=123456 # truncate file to 123456 bytes </code></pre></li> <li> <p>если вы хотите перезаписать данные в середине файла, опять же, это возможно в api-интерфейсе underyling путем <a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html">открытия</a> файла для записи без усечения (и вызова <a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/lseek.html"><code>lseek</code>)</a> чтобы переместиться в нужную позицию при необходимости), но только <code>dd</code> может открыть файл без усечения или добавления, или <a href="https://unix.stackexchange.com/questions/8852/is-there-a-search-utility-which-can-binary-split-search-a-large-sorted-sequentia">поиск</a> из командной консоли ( <a href="https://unix.stackexchange.com/questions/11067/is-there-a-way-to-modify-a-file-in-place/11114#11114">более сложный пример</a> ).</p> <pre><code># 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 </code></pre></li> </ul><p>итак ... как системный инструмент, <code>dd</code> практически бесполезен. как инструмент обработки текста (или двоичного файла), он весьма ценен!</p>

<p>команда <code>dd</code> содержит множество опций, которые cat не может вместить. возможно, в ваших случаях использования cat является подходящей заменой, но это не замена dd.</p><p>одним из примеров будет использование <code>dd</code> для копирования части чего-либо, но не всего. возможно, вы хотите извлечь некоторые биты из середины iso-образа или таблицы разделов с жесткого диска, основываясь на известном месте на устройстве. с помощью <code>dd</code> вы можете указать параметры запуска, остановки и количества, которые разрешают эти действия.</p><p>эти опции <code>dd</code> делают его незаменимым для тонкой обработки данных, тогда как <code>cat</code> * может работать только с целыми файловыми объектами, устройствами или потоками.</p><p>* как отметил жиль в комментариях, можно комбинировать <code>cat</code> с другими инструментами, чтобы изолировать части чего-либо, но <code>cat</code> по-прежнему работает со всем объектом.</p>

<p>никто еще не упомянул, что вы можете использовать dd для создания <a href="http://en.wikipedia.org/wiki/sparse\_file">разреженных файлов</a> , хотя <code>truncate</code> также можно использовать для той же цели.</p><pre><code>dd if=/dev/zero of=sparse-file bs=1 count=1 seek=10gb </code></pre><p>это почти мгновенно и создает произвольный большой файл, который можно использовать, например, в качестве петлевого файла:</p><pre><code>loop=`losetup --show -f sparse-file` mkfs.ext4 $loop mkdir myloop mount $loop myloop </code></pre><p>приятно то, что изначально он использует только один блок дискового пространства, а затем увеличивается только по мере необходимости (форматирование ext4 файла 10 гб в моей системе занимает 291 мб). используйте <code>du</code>, чтобы увидеть, сколько фактически места на диске используется - <code>ls</code> сообщает только о максимальном размере, до которого может увеличиться файл.</p>

<p>переопределение определенных сегментов жесткого диска чем-то - типичный пример. например, вы можете удалить mbr с помощью этой команды:</p><pre><code>dd if=/dev/zero of=/dev/sda bs=446 count=1 </code></pre><p>также вы можете создавать пустые файлы с ним (скажем, для циклических образов дисков):</p><pre><code>dd if=/dev/zero of=10mb.file bs=1024k count=10 </code></pre>

<p><code>dd</code> очень полезно для резервного копирования загрузочного сектора жесткого диска или другого устройства хранения (<code>dd if=/dev/sda of=boot\_sector.bin bs=512 count=1</code>), а затем переписать его (<code>dd if=boot\_sector.bin of=/dev/sda</code>). это также полезно для резервного копирования заголовков зашифрованных томов.</p><p><code>cat</code>, возможно, можно было бы сделать это, но я бы не стал доверять этому при переписывании. трудно заставить <code>cat</code> читать/записывать только определенное количество байтов.</p>

<p>у меня недавно была причина клонировать несколько разделов размером в несколько сотен гигабайт впервые в моей истории linux (c.f <code>cp -ar</code> или <code>rsync</code>, которые служили мне много раз). конечно, я обратился к <code>dd</code>, потому что все знают, что это то, что вы используете ... и был потрясен производительностью. небольшое приближение к гуглу вскоре привело меня к <a href="http://www.gnu.org/software/ddrescue/manual/ddrescue\_manual.html"><code>ddrescue</code></a> , который я уже использовал несколько раз и работает великолепно (намного быстрее, чем dd).</p>

<p>вот несколько трюков, которые я придумал за эти годы.</p><h2><strong>вырежьте и вставьте в недружелюбный tash или неинтерактивный режим bash</strong></h2><p>если вы находитесь в ситуации, когда eof/^ d/^ f не обнаружен, вы можете использовать dd для передачи текстовых файлов на хост. так как он остановит чтение после указанного количества байтов автоматически.</p><p>я использовал это совсем недавно, в прошлом году, во время учений по безопасности, когда мы смогли получить нетитовые оболочки на удаленном хосте и нуждались в передаче файлов.</p><p>на самом деле, я даже создал пару двоичных файлов, кодируя их с помощью base64 и используя медленный, но надежный сценарий декодирования с использованием чистого bash base64.</p><pre><code>dd of=textfile.txt bs=1 count=<size\_of\_data\_in\_paste\_buffer> </code></pre><p>очень крутой трюк в том, что во время работы dd, если вы отправите ему сигнал usr1, он выдаст свое текущее состояние (считанные байты, байты в секунду ...)</p><h2><strong>универсальный фильтр состояния пропускной способности</strong></h2><p>я написал это, чтобы действовать как чистый фильтр прогресса bash для любой программы, которая генерирует данные через стандартный вывод. (примечание: практически все что угодно будет генерировать данные через stdout - для программ, которые этого не делают, вы можете обмануть, если они не будут раздражать вас, используя/dev/stdout в качестве имени файла. но идея в основном заключается в том, что каждый раз, когда вы получаете x количество байтов, печатные хеш-метки (как в старом школьном ftp, когда у вас включен хеш-режим)</p><p>(примечание) файл с прогрессом хромает, в основном это было доказательством концепции. если бы я переделал это, я бы просто использовал переменную.</p><pre><code> 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 <strong>файлы фрагментов с использованием анонимных файловых дескрипторов оболочки</strong>вот чрезвычайно псевдокодовый пример того, как вы можете иметь подписанный 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}) </code></pre><p>я считаю, что дд невероятно полезен. и это только три примера, которые я могу придумать не покладая рук.</p>

<p>вы можете перенаправить некоторый выходной контент. это особенно полезно, если вам нужно написать с помощью <code>sudo</code>:</p><pre><code>echo some\_content | sudo dd status=none of=output.txt </code></pre><p>помимо <code>sudo</code> это эквивалентно:</p><pre><code>echo some\_content > output.txt </code></pre><p>или к этому:</p><pre><code>echo some\_content | sudo tee output.txt > /dev/null </code></pre>