Wie kann man ein Bild mit dd erneut lesen, so dass es mit einem übereinstimmt, das Sie gerade geschrieben haben?

4

Ich habe ein ~ 1-GB-Image, das ich über das ddTool auf eine 8-GB-SD-Karte schreibe . Ich möchte überprüfen, ob es ohne Korruption geschrieben wurde, indem ich es zurücklese und seinen Hash mit dem Original vergleiche.

Wenn ich es über dddie Größe des resultierenden Bildes zurücklese, stimmt es natürlich mit der Größe meiner SD-Karte überein, weshalb das Überprüfen von Hashes nutzlos ist.

Ich glaube, dass ich die Ausgabe des Schreibaufrufs irgendwie interpretieren sollte , um die skip/ count-Parameter so zu konfigurieren , dass sie richtig zurückgelesen werden.

Befehl, mit dem ich mein Bild geschrieben habe:

> sudo dd if=my.img of=/dev/sdc bs=1M 
8+50581 records in
8+50581 records out
3947888640 bytes (3.9 GB) copied, 108.701 s, 36.3 MB/s

Befehl, mit dem ich mein Bild gelesen habe:

> sudo dd if=/dev/sdc of=same_as_my.img
15523840+0 records in
15523840+0 records out
7948206080 bytes (7.9 GB) copied, 285.175 s, 27.9 MB/s
Kentzo
quelle
Warum möchten Sie einige Teile überspringen? Haben Sie nicht am Anfang der Karte, sondern mit einem Versatz geschrieben?
Gilles
@ Gilles Weil die Größe des Bildes, das ich schreibe, kleiner ist als die Größe meiner SD. Bitte überprüfen Sie die aktualisierte Q.
Kentzo

Antworten:

4

Bestimmen Sie die Größe des Bildes zum Beispiel mit \ls -l my.img(nicht ls -lh, das würde Ihnen eine ungefähre Größe geben; \lsschützt vor einem Alias ​​wie ls='ls -h') oder mit stat -c %s my.img.

Wenn Sie die Kopie nur einmal mit dem Original vergleichen möchten, vergleichen Sie einfach die Dateien. Die Verwendung von Hashes ist für einen einmaligen Vergleich nutzlos. Sie würde die Dinge nur langsamer machen und mehr Befehle erfordern. Der Befehl cmpvergleicht Binärdateien. Sie müssen ihm die Bilddatei und den entsprechenden Teil der SD-Karte übergeben. Verwenden Sie headdiese Taste, um den Anfang der SD-Karte zu extrahieren.

</dev/sdc head -c "$(stat -c %s my.img)" | cmp - my.img

Wenn Sie viele Vergleiche durchführen möchten, sind Hashes hilfreich, da Sie jede Instanz nur einmal lesen müssen, um ihren Hash zu berechnen. Jeder Hash ist ausreichend, da Sie sich Sorgen um Datenkorruption machen. Wenn Sie überprüfen erforderlich , dass eine Datei aus Sicherheitsgründen nicht geändert wurde, dann cksumund md5sumwürde nicht geeignet sein, sollten Sie verwenden sha256sumoder sha512sumstatt.

md5sum <my.img >my.img.md5sum
</dev/sdc head -c "$(stat -c %s my.img)" | md5sum >sd-copy.md5sum
cmp my.img.md5sum sd-copy.md5sum

Beachten Sie die Eingabeumleitung im ersten Befehl. Dadurch wird sichergestellt, dass die Prüfsummendatei keine Dateinamen enthält, sodass Sie die Prüfsummendateien vergleichen können. Wenn Sie eine Prüfsummendatei und eine zu überprüfende Kopie haben, können Sie die Prüfung direkt mit durchführen

</dev/sdc head -c "$(stat -c %s my.img)" | md5sum -c my.img.md5sum

Oh, und nicht verwendendd , es ist langsam (oder bestenfalls nicht schneller) und erkennt keine Kopierfehler.

Gilles
quelle
1

Was wir getan haben, war md5umdie eigentliche Partition. Es erlaubt Ihnen nicht genau, das Image mit der Festplatte zu prüfen, aber wenn Sie ein paar Festplatten haben (wie wir), können Sie die 'richtige' Prüfsumme erstellen.

In unserem Fall sehen die Partitionen beispielsweise so aus:

$ sudo fdisk -l /dev/sdc
Disk /dev/sdc: 7948 MB, 7948206080 bytes
245 heads, 62 sectors/track, 1021 cylinders, total 15523840 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1            8192      122879       57344    c  W95 FAT32 (LBA)
/dev/sdc2          122880     7710719     3793920   83  Linux

Wir können dann einfach einen Hash für die Partition (en) generieren mit:

$ sudo md5sum /dev/sdc2

Dies setzt jedoch Folgendes voraus:

  • Sie haben mehrere SD-Karten, mit denen Sie testen können
  • Sie mounten die SD-Karte nicht, bevor Sie den Hash ausführen

Beachten Sie auch, dass Sie nicht die gesamte Festplatte prüfen können (dh '/ dev / sdc' im obigen Beispiel), da dies einen anderen Hash ergibt, der auf den Eigenschaften der SD-Karte basiert.

vpetersson
quelle
0

md5sum wäre hier eine gute lösung, um den wert der image-datei mit dem der sd-karte zu vergleichen.

Steve
quelle
Bitte überprüfen Sie die aktualisierte Frage. Das Problem besteht darin, dass Sie genau dasselbe Bild zurücklesen, um deren Hashes zu berechnen.
Kentzo
0

Schreiben Sie es in ein Dateisystem auf der SD-Karte? Oder direkt? Sie müssen zählen, wenn Sie die Lauflänge der verglichenen Daten begrenzen möchten?

dd sollte Ihnen mitteilen, wie viele Bytes kopiert wurden.

Dies muss erfasst und mit den entsprechenden Werten bs = x und count = y verwendet werden. Auf diese Weise soll vermieden werden, dass in einer Clusterspitze Hashing-Müll entsteht.

BEARBEITEN

Erfassen Sie die Ausgabe. Dies ist die gewünschte Zeile. Verwenden Sie grep für Bytes.

254033920 bytes (254 MB) copied, 1.198 s, 212 MB/s

also (entschuldigen Sie Ausführlichkeit und Backticks).

# original dd
dd if=/path/to/file of=/dev/sdc 2> tempfile
# get bytes
CNT=`cat tempfile | grep bytes | cut -d' ' -f1`
# copy it back by byte
dd bs=1 count=$CNT if=/dev/sdc of=/path/to/copy 

Dies wird langsam sein, daher müssen Sie (und ich werde es hier nicht tun) zuerst die optimale Blockgröße und die Anzahl der zu lesenden ganzen Vielfachen berechnen und dann den Rest mit einem Sprung / Suchvorgang abrufen.

Ein besserer Ansatz wäre es jedoch, eine aufgerundete Anzahl von Blöcken zurückzulesen und den Hash auf einer verkürzten Länge auszuführen. Das Ziel besteht darin, nicht das gesamte Gerät zu lesen, wenn dies nicht erforderlich ist.

mckenzm
quelle
Ich schreibe als Blockgerät auf eine SD-Karte, das heißt also direkt . Können Sie erklären, wie man das Ergebnis eines Schreibvorgangs interpretieren kann, um das Lesen richtig zu konfigurieren?
Kentzo
1
Ich habe es versucht. Sie wollen die Obergrenze von Bytes / Blocksize sagen wir Bytes / 4096 aufgerundet. dann erhalten Sie diese Anzahl von Blöcken in eine neue Datei. md5sum akzeptiert keinen Lauflängenparameter. Mann abgeschnitten und Mann md5sum für mehr. Wenn Sie kein Hashing wollen, versuchen Sie diff oder vimdiff, aber cmp ist genauso gültig.
McKenzm
0
sudo sh -c '
     dd bs=64k if="$1" of="$2"
     ! cmp -- "$1" "$2" 2>&1 |
       grep -qvF "EOF on $1"
' -- my.img /dev/sdc

cmpvergleicht zwei Dateien Byte für Byte und gibt sie zurück, je nachdem, ob sie identisch sind oder nicht. Wenn eine Datei kürzer ist als die andere, aber beide Dateien über die gesamte Länge der kürzeren Datei identisch sind, cmpwird 1 zurückgegeben und EOF on <shorter file>...an stderr gemeldet . Wenn beide Dateien identisch sind, cmpwird 0 zurückgegeben und es wird überhaupt nichts gemeldet. Wenn sie sich jedoch sonst unterscheiden, cmpwird 1 zurückgegeben und das Byte angegeben, in dem sie sich unterscheiden. Die obige Anweisung gibt also 1 für jeden cmpLauf zurück, der eine Ausgabezeile für stdout oder stderr erzeugt, die nicht mit EOF on $1oder 0 übereinstimmt .

mikeserv
quelle
0

IMO ist die beste (einfachste) Möglichkeit, dies zu tun. Verwenden Sie bei Verwendung von dd eine Byte-Größe (bs =), die gleichmäßig in Ihre Quelldatei unterteilt werden kann. Dies führt zu einer ganzen Anzahl von Blockschreibvorgängen. Dann können Sie den Vorgang umkehren (zurücklesen), indem Sie sicherstellen, dass die genaue Anzahl der Bytes von uns im Befehl read sowohl bs = als auch count = gelesen wird - und durch das Prüfsummenprogramm leiten.

Beispiel:

ls

-rw-rw-r-- 1 1006632960 myfile.iso

Generiere eine Checksumme:

sha256sum myfile.iso

8012fcba8bf71a7dd9e8179af40bce0fec57bb84b7426e4de807130ada63243d myfile.iso

Die Dateigröße 1006632960 ist teilbar durch 512. Also benutze dd:

sudo dd if = myfile bs = 512b von = / dev / sdi

ergibt diese Ausgabe:

3840 + 0 Datensätze in

3840 + 0 Datensätze aus

Das +0 ist hier der wichtige Teil. Wenn Sie etwas anderes als +0 sehen, benötigen Sie eine andere Bytesize in Ihrem Befehl dd.

Verwenden Sie dann den folgenden Befehl, um die Ergebnisse zu überprüfen:

sudo dd if = / dev / sdi bs = 512b count = 3840 | sha256sum

und die Ausgabe stimmt mit der vorherigen sha256sum überein, was bedeutet, dass es sich um eine gute Kopie handelt:

3840 + 0 Datensätze in

3840 + 0 Datensätze aus

1006632960 Bytes (1,0 GB, 960 MiB) kopiert, 14,788 s, 68,1 MB / s

8012fcba8bf71a7dd9e8179af40bce0fec57bb84b7426e4de807130ada63243d -

Das Schwierigste ist, die Bytesize richtig zu machen. Sobald Sie es haben, ist der Rest einfach.

Stuart K. Smith
quelle