Резюме: dd
капризный инструмент, который трудно использовать правильно. Не используйте его, несмотря на многочисленные уроки, которые говорят вам об этом. dd
к нему прикреплена атмосфера «Unix Street Credit» - но если вы действительно понимаете, что делаете, вы будете знать, что вам не следует прикасаться к нему 10-футовым шестом.
dd
совершает один вызов read
системного вызова на блок (определяется значением bs
). Нет гарантии, что read
системный вызов вернет столько данных, сколько указано в размере буфера. Это работает для обычных файлов и блочных устройств, но не для каналов и некоторых символьных устройств. См. Когда dd подходит для копирования данных? (или, когда read () и write () частично) для получения дополнительной информации. Если read
системный вызов возвращает менее одного полного блока, то dd
передается частичный блок. Он по-прежнему копирует указанное количество блоков, поэтому общее количество переданных байтов меньше запрашиваемого.
Предупреждение о «частичном чтении» говорит вам именно об этом: одно из чтений было частичным, поэтому dd
передан неполный блок. В подсчете блоков +1
означает, что один блок был прочитан частично; так как количество выводов равно +0
, все блоки были записаны как прочитанные.
Это не влияет на случайность данных: все dd
записываемые байты являются байтами, из которых они считывают /dev/urandom
. Но вы получили меньше байтов, чем ожидалось.
Linux принимает /dev/urandom
произвольные большие запросы (source: extract_entropy_user
in drivers/char/random.c
), поэтому dd
обычно безопасен при чтении с него. Однако чтение больших объемов данных требует времени. Если процесс получает сигнал, read
системный вызов возвращается до заполнения своего выходного буфера. Это нормальное поведение, и приложения должны вызываться read
в цикле; dd
не делает этого по историческим причинам ( dd
происхождение мрачное, но, похоже, оно начиналось как инструмент для доступа к лентам, которые имеют особые требования и никогда не были приспособлены для использования в качестве инструмента общего назначения). Когда вы проверяете прогресс, он посылает dd
процессу сигнал, который прерывает чтение. У вас есть выбор между знанием, сколько байтовdd
полная копия воли (убедитесь, что она не прерывается - нет проверки хода выполнения, нет приостановки) или известно, сколько байтdd
до сих пор скопировал, и в этом случае вы не можете знать, сколько еще байтов будет скопировано.
Версия dd
в GNU coreutils (как в не встроенных Linux и в Cygwin) имеет флаг, fullblock
который указывает dd
на вызов read
в цикле (и то же для write
) и, таким образом, всегда передает полные блоки. Сообщение об ошибке предполагает, что вы используете его; Вы должны всегда использовать его (как во входных, так и в выходных флагах), за исключением особых случаев (в основном, при доступе к лентам) - если вы используете dd
вообще, то есть: обычно есть лучшие решения (см. ниже).
dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000
Другой возможный способ быть уверенным в том, dd
что нужно сделать, - передать размер блока, равный 1. Затем вы можете сказать, сколько байтов было скопировано из числа блоков, хотя я не уверен, что произойдет, если read
прервать a перед чтением первого байт (что не очень вероятно на практике, но может случиться). Однако, даже если это работает, это очень медленно.
Общие рекомендации по использованию dd
является не использоватьdd
. Хотя dd
часто объявляется как команда низкого уровня для доступа к устройствам, на самом деле это не так: все волшебство происходит в части файла (the /dev/…
) устройства, dd
это просто обычный инструмент с высоким потенциалом для неправильного использования, что приводит к потере данных , В большинстве случаев есть более простой и безопасный способ сделать то, что вы хотите, по крайней мере, в Linux.
Например, чтобы прочитать определенное количество байтов в начале файла, просто вызовите head
:
head -c 1000000m </dev/urandom >file
Я сделал быстрый тест на моей машине и не заметил различий в производительности между dd
большим размером блока и head
.
Если вам нужно пропустить несколько байтов в начале, отправьте tail
в head
:
dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output
Если вы хотите увидеть прогресс, позвоните, lsof
чтобы увидеть смещение файла. Это работает только для обычного файла (выходного файла в вашем примере), а не для символьного устройства.
lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1
Вы можете позвонить, pv
чтобы получить отчет о ходе работы (лучше, чем у dd
), за счет дополнительного элемента в конвейере (с точки зрения производительности, он едва заметен).