
Я создаю файл размером 1 ТБ со случайными данными с помощью dd if=/dev/urandom of=file bs=1M count=1000000
. Теперь я проверяю kill -SIGUSR1 <PID>
прогресс и получаю следующее:
691581+0 Datensätze ein
691580+0 Datensätze aus
725174190080 Bytes (725 GB) kopiert, 86256,9 s, 8,4 MB/s
800950+1 Datensätze ein
800950+0 Datensätze aus
839856947200 Bytes (840 GB) kopiert, 99429,5 s, 8,4 MB/s
dd: warning: partial read (809620 bytes); suggest iflag=fullblock
803432+1 Datensätze ein
803431+1 Datensätze aus
842459273876 Bytes (842 GB) kopiert, 99791,3 s, 8,4 MB/s
Я не могу интерпретировать предупреждение. Что оно говорит? Действительно ли мой файл случайный после предупреждения или есть проблема? Что означает +0 или +1 в 800950+1 Datensätze ein
и 800950+0 Datensätze aus
? После предупреждения это +1. Это errorcount?
решение1
Резюме: dd
капризный инструмент, который трудно использовать правильно. Не используйте его, несмотря на многочисленные руководства, которые говорят вам об этом. dd
имеет привкус «unix street cred» — но если вы действительно понимаете, что делаете, вы будете знать, что вам не следует трогать его даже 10-футовым шестом.
dd
делает один вызов системного read
вызова на блок (определяется значением bs
). Нет гарантии, что read
системный вызов вернет столько данных, сколько указан размер буфера. Это обычно работает для обычных файлов и блочных устройств, но не для каналов и некоторых символьных устройств. СмотритеКогда dd подходит для копирования данных? (или когда read() и write() являются частичными)для получения дополнительной информации. Если read
системный вызов возвращает менее одного полного блока, то dd
передает частичный блок. Он все равно копирует указанное количество блоков, поэтому общее количество переданных байтов меньше запрошенного.
Предупреждение о «частичном чтении» говорит вам именно об этом: одно из чтений было частичным, поэтому dd
был передан неполный блок. В счетчиках блоков +1
означает, что один блок был прочитан частично; поскольку выходной счетчик равен +0
, все блоки были записаны как прочитанные.
Это не влияет на случайность данных: все байты, которые dd
записываются, являются байтами, которые он считывает /dev/urandom
. Но вы получили меньше байтов, чем ожидали.
Linux /dev/urandom
обрабатывает произвольно большие запросы (источник:extract_entropy_user
в 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 of=file bs=1M count=1000000
Другой возможный способ убедиться в том, что dd
будет сделано, — это передать размер блока 1. Тогда вы сможете узнать, сколько байт было скопировано из количества блоков, хотя я не уверен, что произойдет, если a read
будет прерван до чтения первого байта (что на практике маловероятно, но может случиться). Однако, даже если это сработает, это очень медленно.
Общий совет по использованию dd
:не использоватьdd
. Хотя dd
часто рекламируется как низкоуровневая команда для доступа к устройствам, на самом деле это не так: вся магия происходит в файле устройства (часть /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
у ), за счет дополнительного элемента в конвейере (с точки зрения производительности это едва заметно).
решение2
Предупреждение появляется, когда dd
не удалось получить достаточно данных для заполнения блока за одно чтение. Это происходит с нестабильными или медленными источниками данных или источниками, которые записывают данные в меньших единицах, чем запрошенный вами размер блока.
Проблем с целостностью данных нет, но проблема в том, что dd
частичное чтение все равно считается прочитанным блоком.
Если вы не используете эту count
опцию, предупреждение вряд ли имеет значение, это просто соображения производительности. Но с count
, вы не получите запрошенный объем данных. Из-за частичных чтений of
будет меньше, чем count*bs
в конце.
Поэтому, когда вы используете count
, технически вы всегда должны использовать iflag=fullblock
также .
Должно +x
быть указано количество частичных блоков.
решение3
< /dev/urandom \
dd ibs=4k obs=64k |
dd bs=64k count=16000000 >file
^Это просто сработает. Дезинформация, которая здесь была, явно ложна. dd
Буферыявныйи так, для буферизации входных данныхсчитатьвхождения, которые вам нужно явно буферизировать. Вот и все. Не покупайтесь на эту чушь.