Створіть випадкові дані за допомогою DD та отримайте "часткове попередження про читання". Чи справді дані після попередження справді випадкові?


16

Я створюю 1TB файл із випадковими даними 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. Це кількість помилок?


На це було б легше відповісти, якби ви могли перекласти повідомлення англійською мовою. Також визначте "дійсно випадковий". Який рівень випадковості вам потрібен, для чого ви будете використовувати його?
terdon

Щоб отримати англійські повідомлення, використовуйте LC_ALL=Cперед командою, наприкладLC_ALL=C dd if=...
Volker Siegel

Відповіді:


38

Короткий зміст: ddце химерний інструмент, який важко правильно використовувати. Не використовуйте його, незважаючи на численні підручники, які вам так говорять. ddдо нього прикріплена вібрація «unix street Credit» - але якщо ви справді зрозумієте, що ви робите, ви знатимете, що не слід торкатися її 10-футовим полюсом.

ddробить один виклик до readсистемного виклику на блок (визначається значенням bs). Немає гарантії, що readсистемний виклик повертає стільки даних, скільки вказаний розмір буфера. Це, як правило, працює для звичайних файлів і блокових пристроїв, але не для труб та деяких пристроїв символів. Дивіться, коли dd підходить для копіювання даних? (або, коли читаються () та записуються () частково) для отримання додаткової інформації. Якщо 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скопійовано до цього часу, і в цьому випадку ви не можете знати, скільки ще байтів буде скопійовано.

У версії ddGNU coreutils (як це знайдено в невбудованому Linux та Cygwin) є прапор, fullblockякий говорить ddпро дзвінок readу циклі (та ditto для write) та таким чином завжди передає повні блоки. Повідомлення про помилку говорить про те, що ви використовуєте його; ви завжди повинні використовувати його (як у вхідних, так і у вихідних прапорах), за винятком дуже особливих обставин (переважно під час доступу до стрічок) - якщо ви ddвзагалі використовуєте , тобто: зазвичай є кращі рішення (див. нижче).

dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000

Ще один можливий спосіб бути впевненим у тому dd, що робити, - це передати розмір блоку 1. Тоді ви можете сказати, скільки байтів було скопійовано з підрахунку блоків, хоча я не впевнений, що буде, якщо 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
+1. Це одна з найбільш добре досліджених публікацій, яку я читав у мережі StackExchange за довгий час. Він є коротким, але містить усі деталі (історичні та сучасні) про ddкоманду, яку я не розумів, що мені потрібно знати. Спасибі.
Космічна Оссифараж

4
Вибачте, але я не погоджуюся з вашим твердженням, що dd - це "химерний інструмент, який важко правильно використати" та "не використовувати DD". Це ідеально корисна утиліта, коли її правильно використовують хтось, хто знайшов час, щоб зрозуміти це. Насправді дискові криміналістичні набори інструментів майже всі залежать від dd або такої похідної, як dcfldd.
fpmurphy

1
@ fpmurphy1 GNU ddможна використовувати безпечно, завдяки своєму fullblockваріанту. Але якщо у вас є GNU coreutils, вам не потрібно ddбагато. «Похідні» , такі , як dcflddє НЕ dd , вони не страждають від його конструктивних недоліків, так що моя відповідь не відноситься до них. Переважна, переважна більшість людей, які користуються dd, не потребували достатнього часу, щоб зрозуміти це (щонайбільше, вони знайшли час, щоб подумати, що вони це розуміють), і спосіб їх використання це призводить до втрати даних.
Жил "ТАК - перестань бути злим"

1
@Gilles Отже, ми не повинні використовувати "ехо" б / з його потенціалу для неправильного використання (sudo echo hello world> / dev / sda)?
whitey04

2
@ whitey04 Я не рекомендую поводитися з бочками нітрогліцерину. Я не казав, що не слід використовувати сірники.
Жил "ТАК - перестань бути злим"

9

Попередження виникає, коли 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буфери явні і так, щоб ввести буфер для підрахунку подій, які вам потрібно явно буферувати. Це все. Не купуйте фуд.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.