Резюме: 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_userin 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), за счет дополнительного элемента в конвейере (с точки зрения производительности, он едва заметен).