dd

Aus wiki.archlinux.de

dd ist ein Programm für das sehr systemnahe Kopieren und Ändern von Daten. „dd“ ist eine Abkürzung für „dataset definition“ in IBMs Job Control Language. Die Syntax des Programms unterscheidet sich grundlegend von der Syntax anderer Programme und ist sehr an die Syntax der JCL angelehnt.

Mittels dd können zum Beispiel Images von Wechseldatenträgern erstellt werden, es können aber auch Images auf Wechseldatenträger geschrieben werden. Außerdem kann mittels dd ein Systembackup vorgenommen werden, Arbeitsspeicherauszüge erstellt werden, oder aber auch Datenträger „geleert“ werden.

dd ist ein nicht häufig verwendetes, aber sehr mächtiges, und wenn es drauf ankommt, sehr zuverlässiges Programm.

Verfügbarkeit

dd gehört zu den „core utils“ und ist somit Bestandteil einer jeden Grundinstallation von Linux. Es braucht daher nicht explizit installiert zu werden.

Es gibt Implementierungen von dd, die durch weitere Funktionen auf das Wiederherstellen von Daten optimiert wurden. Bekannte Vertreter hiervon sind „dd_rescue“ und „GNU ddrescue“

Verwendung

Aufgrund der Syntax unterscheidet sich die Verwendung von dd grundlegend von der Verwendung anderer Programme. Nachfolgende Beispiele erläutern die von dd benutzte Syntax und stellen einige wichtige Parameter vor.

Parameter werden immer in der Form „bezeichnung=wert“ angegeben.

if und of

Die beiden am häufigsten verwendeten Parameter sind „if“ und „of“, dies steht für „in file“ (Eingabedatei) bzw. „out file“ (Ausgabedatei). Gemäß der Unix-Philosophie, alles als Dateien zu repräsentieren, können selbstverständlich auch Partitionen, der Arbeitsspeicher oder Mauseingaben als Datei angegeben werden.

dd if=testfile of=neu
1890+1 Datensätze ein
1890+1 Datensätze aus
967789 Bytes (968 kB) kopiert, 0,00913792 s, 106 MB/s

Hier wurde als Eingabedatei „testfile“ verwendet. Zur Ausgabe wurde eine Datei „neu“ Angegeben. Wenn dd die Eingabedatei komplett verarbeitet hat, werden noch statistische Informationen ausgegeben.

Wenn „if“ weggelassen wird, wird davon ausgegangen, dass für Eingabe STDIN verwendet wird.

dd of=output
Ausgabe, die in die Datei „output“ geschrieben wird.
0+1 Datensätze ein
0+1 Datensätze aus
57 Bytes (57 B) kopiert, 21,2278 s, 0,0 kB/s

Hier wird der Text Ausgabe, die in die Datei „output“ geschrieben wird. – in die Datei „output“ geschrieben. Stattdessen kann hier auch durch eine Pipe etwas nach STDIN von dd geleitet werden, etwa die Ausgabe eines Auslesetools für irgendetwas.

Analog dazu kann auch „of“ weg gelassen werden, um die Ausgabe direkt auf STDOUT zu schreiben.

bs und count

Will man nur eine gewissen Bereich der Daten aus der Eingabedatei lesen, kann man sich der Parameter „bs“ und „count“ bedienen. Über „bs“ definiert man die so genannte „Block-Größe“ und mittels „count“ gibt man an, wie viele Blöcke man auslesen möchte. Ohne Angabe von „bs“ wird jedes Byte einzeln kopiert, was sich negativ auf die Kopierdauer auswirken kann, da viel öfter die Position auf den Zielmedium gesucht, reserviert und geschrieben werden muss. Vor allem bei SSDs und Speicherkarten sollte das Wear-leveling bzw. die jeweilige Lebensdauer des Mediums nicht durch unnötige Schreibzyklen belastet werden. mit „bs=1M“ ist man schon auf der sicheren Seite.

dd if=/dev/zero of=benchmark bs=1GB count=1
1+0 Datensätze ein
1+0 Datensätze aus
1000000000 Bytes (1,0 GB) kopiert, 13,6864 s, 73,1 MB/s

Hier wird zu Testzwecken ein ein Gigabyte großer Block aus /dev/zero ausgelesen und als Datei „benchmark“ gespeichert. Anhand der Statistik-Informationen kann nun ermittelt werden, wie schnell die Festplatte ist. Wenn man den Test mit einer anderen Festplatte wiederholt, bekommt man vergleichbare Werte.

dd verhält sich hier SI-Konform, das heißt, die Angaben beziehen sich nicht auf die Basis 2, sondern auf die Basis 10. Ein Gigabyte sind nicht 1.073.741.824 Byte, sondern 1.000.000.000 Byte. Will man hingegen die „klassische Basis“ 2 verwenden, lässt man einfach „B“ weg.

dd if=/dev/zero of=benchmark bs=1G count=1
1+0 Datensätze ein
1+0 Datensätze aus
1073741824 Bytes (1,1 GB) kopiert, 14,5439 s, 73,8 MB/s

Da dd trotzdem SI-konform rechnet, wird hier nicht, wie im ersten Beispiel „1,0 GB“ angezeigt, sondern eben etwas mehr.

Möchte man statt einem Gigabyte vielleicht 300 Megabyte (SI-Konform) als Grundlage verwenden, geht dies selbstverständlich auch.

dd if=/dev/zero of=benchmark bs=100MB count=3
3+0 Datensätze ein
3+0 Datensätze aus
300000000 Bytes (300 MB) kopiert, 3,49806 s, 85,8 MB/s

Hier wird eine Blockgröße von 100 Megabyte definiert, und ein Count von 3 angegeben, es werden also 3 100-Megabyte-Blöcke ausgelesen, was in der Summe dann 300 Megabyte ergibt. Auch hier kann man durch weglassen des „B“ in der Blockgrößen-Definition die „alte“ Angabe mit Basis 2 verwenden. Alternativ ginge auch „bs=300MB count=1“.

Durch weglassen des „B“ kann man bei allen Größenangaben die Basis 2, anstatt der SI-Konformen Basis 10 verwenden. Alle Größenangaben können also um einem multiplizierenden Suffix ergänzt werden. Folgende Tabelle stellt dies dar.

Suffix Multiplikator Ergebnis
c 1 Byte (Standard wenn nicht angegeben)
w 2 Word (= 16 Bit)
b 512 Größe eines Sektors Wikipedia: CHS
kB 1000 Kilobyte
K 1024 Kibibyte
MB 1000×1000 Megabyte
M 1024×1024 Mebibyte
GB 1000×1000×1000 Gigabyte
G 1024×1024×1024 Gibibyte

Kibibyte, Mebibyte und Gibibyte sind jeweils die Angaben mit der Basis 2, die Bezeichnungen hierfür wurden von der IEC eingeführt, um zwischen binärer und dezimaler Basis unterscheiden zu können.

Die Multiplikations-Angaben in dd können nach selbem Schema für Terabyte (T), Petabyte (P), Exabyte (E), Zettabyte (Z) und Yottabyte (Y) fortgesetzt werden.

Weitere Parameter

Neben den oben genannten Parametern verfügt dd noch über einige weitere Parameter, die allerdings weniger häufig benutzt werden. Daher seien hier nur kurz die wichtigsten angerissen.

  • status=noxfer unterdrückt die Ausgabe der statistischen Informationen über den Transfer der Daten.
  • Die Parameter seek=N und skip=N sind vor allem in Kombination mit ibs und obs von Bedeutung, und bestimmen, wie viele Blöcke beim Lesen, bzw. beim Schreiben der Daten übersprungen werden sollen.
  • conv=SYM bestimmt, ob und wenn ja, wie die Eingabedaten konvertiert werden sollen, bevor sie in die Ausgabedatei geschrieben werden. Für SYM können zum Beispiel „noerror“ (bei Fehlern trotzdem fortsetzen), „lcase“ (Eingabe in Kleinbuchstaben wandeln) oder „excl“ (abbrechen, wenn Ausgabedatei existiert) sein.
  • iflag=SYM definiert weitere Flags für das Einlesen. Es können hier zum Beispiel „dsync“ (synchronisieren von Ein- und Ausgabedaten), „nofollow“ (Symlinks nicht nachgehen) oder „nonblock“ (Dateien nicht blockieren) gesetzt werden.

Praxisnahe Beispiele

Nachfolgende Beispiele demonstrieren die Verwendung von dd anhand praxisnaher Aufgaben. Für einige der hier dargestellten Beispiele benötigt man – nicht ohne Grund! – root-Rechte.

Arbeiten mit Datenträgern

Achtung: dd ist ein sehr mächtiges Werkzeug, das ohne Rückfrage auch wichtige Daten unwiederbringlich zerstören kann! Es ist beim Arbeiten mit Partitionen und Datenträgern absolute Vor- und Umsicht geboten!


dd if=/dev/sda3 | gzip -9 > /media/backup/sda3.img.gz

Durch den Aufruf von dd wird hier die Partition „/dev/sda3“ eingelesen. Durch das Weiterleiten an gzip durch die Pipe werden die Daten komprimiert und nach „/media/backup/sda3.img.gz“ geschrieben. Hierdurch wird ein komplettes Backup der Partition angelegt. Die Partition „/dev/sda3“ sollte hierzu allerdings nicht gemountet sein, um Änderungen während des Kopierens auszuschließen.

gunzip -c /media/backup/sda3.img.gz | dd of=/dev/sda3

Hiermit wird das zuvor erstellte Image auf die Partition zurückgeschrieben. Alle auf der Partition vorhandenen Daten werden dadurch gelöscht. Analog dazu kann man auch von Wechseldatenträgern wie CDs oder DVDs auf diese Art ein Image erzeugen.

dd if=/dev/dvd of=dvd-image.img

Hier bei ist es irrelevant, was sich auf dem Datenträger befindet. Auch eventuelle Fehler im Dateisystem werden von dd ignoriert, da es die Daten „direkt von der Hardware“ in Form von Nullen und Einsen ausliest, und nicht in Form von Daten aus dem Dateisystem.

Will man nicht den gesamten Datenträger oder eine Partition kopieren, sondern möchte man lediglich den Bootloader samt Partitionstabelle sichern, erreicht man dies mittels …

dd if=/dev/sda of=mbr-sicherung bs=512 count=1

Der gesamte MBR nebst Partitionstabelle befindet sich nun in der Datei „mbr-sicherung“ im aktuellen Arbeitsverzeichnis.

dd if=mbr-sicherung of=/dev/sda bs=512 count=1

Dies schreibt den MBR samt Partitionstabelle wieder zurück auf die Platte. Möchte man nur den MBR sichern, bzw. zurückschreiben, verwendet man unter Beibehaltung aller Parameter statt 512 einfach 446 als Blockgröße.

Man kann mit dd allerdings nicht nur Images anfertigen oder zurückschreiben, sondern man kann auch Platten „leeren“. Möchte man zum Beispiel eine Festplatte verkaufen, und will vorher alle Daten auf der Platte löschen, kann man dies mittels …

dd if=/dev/urandom of=/dev/sda

… erreichen, wobei „/dev/sda“ natürlich durch die zu „leerende“ Platte ersetzt werden muss.

Arbeiten mit Dateien

Will man, zum Beispiel als Grundlage für die Verschlüsselung einer Festplatte, ein 2048 Bit (= 256 Byte) langen, auf Zufallsdaten basierenden Schlüssel generieren, kann man folgenden Befehl benutzen

dd if=/dev/random of=keyfile bs=256 count=1

Möchte man während des Kopierens von Daten von dd über den aktuellen Stand informiert werden, kann man dem Programm den kill-Befehl mit dem Parameter „-USR1“ senden. Hierdurch wird dd veranlasst, den aktuellen Status auszugeben.

dd if=/dev/zero of=dev/null & pid=$!
[1] 5404

Der Kopierprozess wird gestartet und in den Hintergrund verfrachtet, der Variable „pid“ wird die Prozess-ID von dieser dd-Instanz zugeordnet. Da hier „/dev/zero“ nach „/dev/null“ kopiert wird, und ersteres unbegrenzt Daten abgibt, und letzteres unbegrenzt Daten annimmt, läuft dieser Prozess ewig, und dient hier nur zur Demonstration.

kill -USR1 $pid
14899464+0 Datensätze ein
14899463+0 Datensätze aus
7628525056 Bytes (7,6 GB) kopiert, 9,53511 s, 800 MB/s

Nach kurzer Zeit wird in der selben Shell der kill-Befehl an dd gesendet. Dieses gibt daraufhin den aktuellen Stand des Kopiervorgangs aus.

Die Fortschrittsanzeige kann in neueren Versionen von dd mittels status=progress angezeigt werden! 
Beispiel : dd if=/dev/zero of=dev/null status=progress & pid=$!


kill -USR1 $pid
34236416+0 Datensätze ein
34236416+0 Datensätze aus
17529044992 Bytes (18 GB) kopiert, 21,8631 s, 802 MB/s

Kurz darauf wird der selbe Befehl noch einmal gesendet, um den Fortschritt aufzuzeigen.

Hat man eine Datei, dessen Inhalte in Großschreibung ausgegeben werden sollen, kann man sich des Parameters „conf=ucase“ bedienen. Folgendes Beispiel erläutert dies.

cat dateiklein
Inhalt der Datei.
dd if=dateiklein of=dateigrosz conv=ucase
0+1 Datensätze ein
0+1 Datensätze aus
18 Bytes (18 B) kopiert, 4,1264e-05 s, 436 kB/s
cat dateigrosz
INHALT DER DATEI.

Siehe auch

Weblinks