Erstelle zufällige Daten mit dd und erhalte eine "partielle Lesewarnung". Sind die Daten nach der Warnung nun wirklich zufällig?


16

Ich erstelle eine 1TB Datei mit zufälligen Daten mit dd if=/dev/urandom of=file bs=1M count=1000000. Jetzt überprüfe ich kill -SIGUSR1 <PID>den Fortschritt und erhalte folgendes:

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

Ich kann die Warnung nicht interpretieren. Was sagt es? Ist meine Datei nach der Warnung wirklich zufällig oder liegt ein Problem vor? Was bedeutet +0 oder +1 in 800950+1 Datensätze einund 800950+0 Datensätze aus? Nach der Warnung ist es +1. Ist es eine Fehlerzahl?


Dies wäre einfacher zu beantworten, wenn Sie die Nachrichten ins Englische übersetzen könnten. Definieren Sie auch "wirklich zufällig". Welches Maß an Zufälligkeit benötigen Sie, wofür werden Sie es verwenden?
Terdon

Um englische Nachrichten zu erhalten, verwenden Sie LC_ALL=Cvor dem BefehlLC_ALL=C dd if=...
Volker Siegel

Antworten:


38

Zusammenfassung: ddist ein verschrobenes Werkzeug, das schwer richtig zu bedienen ist. Verwenden Sie es trotz der zahlreichen Tutorials nicht. ddist mit einem „Unix Street Cred“ -Vibe verbunden - aber wenn Sie wirklich verstehen, was Sie tun, werden Sie wissen, dass Sie es nicht mit einer 10-Fuß-Stange anfassen sollten.

ddRuft den readSystemaufruf einmal pro Block auf (definiert durch den Wert von bs). Es kann nicht garantiert werden, dass der readSystemaufruf so viele Daten zurückgibt wie die angegebene Puffergröße. Dies funktioniert in der Regel für reguläre Dateien und Blockgeräte, nicht jedoch für Pipes und einige Zeichengeräte. Siehe Wann eignet sich dd zum Kopieren von Daten? (oder, wenn für weitere Informationen read () und write () partial sind) . Wenn der readSystemaufruf weniger als einen vollständigen Block zurückgibt, wird ddein Teilblock übertragen. Die angegebene Anzahl von Blöcken wird weiterhin kopiert, sodass die Gesamtanzahl der übertragenen Bytes geringer ist als angefordert.

Die Warnung vor einem „teilweisen Lesevorgang“ sagt genau dies aus: Einer der Lesevorgänge war teilweise, sodass ddein unvollständiger Block übertragen wurde. In den Blockzählungen +1bedeutet dies, dass ein Block teilweise gelesen wurde; Da die Ausgabezählung gleich ist +0, wurden alle Blöcke als gelesen ausgeschrieben.

Dies hat keinen Einfluss auf die Zufälligkeit der Daten: Alle Bytes, ddaus denen geschrieben wird, sind Bytes, aus denen gelesen wird /dev/urandom. Aber Sie haben weniger Bytes als erwartet.

Linux unterstützt /dev/urandombeliebig große Anforderungen (source: extract_entropy_userin drivers/char/random.c) und ddist daher normalerweise sicher, wenn Sie davon lesen. Das Lesen großer Datenmengen erfordert jedoch Zeit. Wenn der Prozess ein Signal empfängt, readkehrt der Systemaufruf zurück, bevor der Ausgabepuffer gefüllt wird. Dies ist normal und Anwendungen sollten readin einer Schleife aufgerufen werden . ddtut dies aus historischen Gründen nicht (seine ddUrsprünge sind trübe, aber es scheint als Werkzeug für den Zugriff auf Bänder begonnen zu haben, die besondere Anforderungen haben und niemals als Allzweckwerkzeug angepasst wurden). Wenn Sie den Fortschritt überprüfen, sendet dies dem ddProzess ein Signal, das den Lesevorgang unterbricht. Sie haben die Wahl, wie viele Bytes Sie wissen möchtenddkopiert insgesamt (stellen Sie sicher, dass Sie es nicht unterbrechen - keine Fortschrittskontrolle, keine Unterbrechung), oder Sie wissen, wie viele Bytes ddbis jetzt kopiert wurden. In diesem Fall können Sie nicht wissen, wie viele Bytes kopiert werden.

Die Version von ddin GNU coreutils (wie sie unter nicht eingebettetem Linux und unter Cygwin zu finden ist) hat ein Flag, fullblockdas angibt dd, readin einer Schleife aufzurufen (und dito für write) und somit immer volle Blöcke zu übertragen. Die Fehlermeldung schlägt vor, dass Sie es verwenden; Sie sollten es immer verwenden (sowohl in Eingabe- als auch in Ausgabe-Flags), außer unter ganz besonderen Umständen (meistens beim Zugriff auf Bänder). Wenn ddüberhaupt, gibt es normalerweise bessere Lösungen (siehe unten).

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

Eine andere Möglichkeit, um sicherzugehen, was getan ddwird, besteht darin, eine Blockgröße von 1 zu übergeben. Dann können Sie feststellen, wie viele Bytes aus der Blockanzahl kopiert wurden, obwohl ich nicht sicher bin, was passieren wird, wenn a readvor dem ersten Lesen unterbrochen wird Byte (was in der Praxis nicht sehr wahrscheinlich ist, aber passieren kann). Dies ist jedoch sehr langsam, auch wenn es funktioniert.

Der allgemeine Rat zur Verwendung ddist nicht zu verwendendd . Obwohl ddoft als Befehl auf niedriger Ebene für den Zugriff auf Geräte geworben wird, ist dies in der Tat nicht der Fall: Alles, was in der Gerätedatei geschieht /dev/…, ddist nur ein gewöhnliches Tool mit einem hohen Missbrauchspotenzial, das zu Datenverlust führt . In den meisten Fällen gibt es eine einfachere und sicherere Möglichkeit, das zu tun, was Sie möchten, zumindest unter Linux.

Um beispielsweise eine bestimmte Anzahl von Bytes am Anfang einer Datei zu lesen, rufen Sie einfach Folgendes auf head:

head -c 1000000m </dev/urandom >file

Ich habe auf meiner Maschine einen schnellen Benchmark durchgeführt und keinen Leistungsunterschied zwischen ddmit einer großen Blockgröße und festgestellt head.

Wenn Sie am Anfang einige Bytes überspringen müssen, leiten Sie tailin head:

dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output

Wenn Sie den Fortschritt sehen möchten, rufen Sie lsofauf, um den Dateiversatz anzuzeigen. Dies funktioniert nur für eine reguläre Datei (die Ausgabedatei in Ihrem Beispiel), nicht für ein Zeichengerät.

lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1

Sie können anrufen pv, um einen Fortschrittsbericht (besser als dd) auf Kosten eines zusätzlichen Elements in der Pipeline zu erhalten (in Bezug auf die Leistung kaum wahrnehmbar).


2
+1. Dies ist einer der am besten recherchierten Posts, die ich seit langer Zeit im StackExchange-Netzwerk gelesen habe. Es ist kurz und bündig und enthält alle Details (historisch und aktuell) zu dem ddBefehl, von denen ich nicht wusste, dass ich sie wissen musste. Vielen Dank.
Cosmic Ossifrage

4
Es tut mir leid, aber ich bin nicht einverstanden mit Ihrer Behauptung, dass es sich bei dd um ein "schlecht gelauntes Werkzeug, das nur schwer richtig zu verwenden ist" und "nicht verwenden" handelt. Es ist ein perfektes Hilfsprogramm, wenn es von jemandem richtig verwendet wird, der sich die Zeit genommen hat, es zu verstehen. Tatsächlich hängen forensische Toolkits für Festplatten fast alle von dd oder einem Derivat wie dcfldd ab.
Fpmurphy

1
@ fpmurphy1 GNU ddkann dank seiner fullblockOption sicher verwendet werden . Aber wenn Sie GNU-Coreutils haben, brauchen Sie nicht ddviel. „Derivate“, wie dcflddsind nicht dd , sie nicht von ihren Konstruktionsfehler leiden, so meine Antwort auf sie nicht anwendbar ist . Eine große, große Mehrheit der Benutzer ddhat sich nicht genügend Zeit genommen, um es zu verstehen (höchstens haben sie sich die Zeit genommen, um zu glauben , dass sie es verstehen), und die Art und Weise, wie sie es verwenden, führt zu Datenverlust.
Gilles 'SO- hör auf böse zu sein'

1
@ Gilles Also sollten wir nicht "Echo" b / c von seinem Potenzial für Missbrauch verwenden (Sudo Echo Hallo Welt> / dev / sda)?
Whitey04

2
@ whitey04 Ich empfehle, keine Fässer mit Nitroglycerin zu handhaben. Ich habe nicht gesagt, dass Sie keine Streichhölzer verwenden sollten.
Gilles 'SO- hör auf böse zu sein'

9

Die Warnung tritt auf, wenn ddnicht genügend Daten abgerufen werden konnten, um einen Block in einem Lesevorgang zu füllen. Dies geschieht bei fehlerhaften oder langsamen Datenquellen oder bei Quellen, die Daten in kleineren Einheiten als der von Ihnen angeforderten Blockgröße schreiben.

Es gibt kein Problem mit der Datenintegrität, aber das Problem ist, dass ddein teilweiser Lesevorgang immer noch als Leseblock gezählt wird.

Wenn Sie die countOption nicht verwenden , spielt die Warnung kaum eine Rolle, sondern ist nur ein Leistungsaspekt. Mit erhalten countSie jedoch nicht die von Ihnen angeforderte Datenmenge. Aufgrund teilweiser Lesevorgänge ofwird kleiner als count*bsam Ende.

Also, wenn Sie verwenden count, sollten Sie technisch immer auch verwenden iflag=fullblock.

Das +xsollte die Anzahl der Teilblöcke sein.


-3
< /dev/urandom \
dd ibs=4k obs=64k |
dd bs=64k count=16000000 >file

^ Das wird einfach funktionieren. Die Fehlinformationen, die hier sonst vorlagen, sind offensichtlich falsch. ddDie Puffer von sind explizit. Um Eingaben zu puffern, um Vorkommen zu zählen , müssen Sie explizit puffern. Das ist alles. Kaufen Sie nicht die Fud.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.