Systembackup mit Hilfe von dd

Aus Laub-Home Wiki

Es gibt einige Tools, um Daten unter Linux zu sichern. Man kann z.B. mit cp oder rsync die Daten einfach auf eine externe Festplatte kopieren. Um Partitionen zu sichern bietet sich partimage an. Wenn man jedoch eine komplette Festplatte mit allen darauf befindlichen Partitionen als 1 Image sichern möchte bietet sich das Programm dd an. dd(=diskdump) erstellt eine exakte 1zu1-Kopie eines Datenträgers in dem es byte für byte ausliest und kopiert. Dabei ist es dd ziemlich egal, welche Daten, Partitionen oder Betriebssysteme sich auf der zu kopierenden Platte befinden.

Voraussetzungen

Um mit dd eine Festplatte zu kopieren, darf diese nicht ins Dateisystem eingehängt sein. Will man also ein Backup der Festplatte machen, auf der sich das Betriebssystem befindet, so muss man eine Live-CD dafür verwenden.

Die Live-CD sollte das Programm dd beinhalten (praktisch bei allen der Fall), sollte die Hardware des Computers gut erkennen und sollte Schreibsupport für NTFS-formatierte Datenträger haben, wenn man eine externe Festplatte mit NTFS benutzen möchte. Die neueste Ubuntu Desktop-CD oder PING (Partimage is not Ghost) verfügt z.B. über diesen ntfs-3g Treiber.

Der externe Datenträger sollte über ausreichend Speicherplatz verfügen (später mehr).

Durchführung des Backups

dd fragt NICHT nach, ob es die Aktion wirklich durchführen soll! Daher ist hier Vorsicht geboten! Alle Aufgaben werden in der Konsole erledigt, daher kann man die Live-CD (wenn sie dieses erlaubt) auch im Textmodus starten. Ansonsten muss man nach dem Booten der LiveCD eine Konsole mit Rootrechten öffnen, da die kommenden Aktionen Administratorrechte benötigen.

Zunächst kann man sich mit dem Befehl

fdisk -l

einen Überblick über die Festplatten und Partitionen machen. Meine Ausgabe sieht so aus:

Disk /dev/sda: 40.0 GB, 40007761920 bytes
255 heads, 63 sectors/track, 4864 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xcccdcccd

Device Boot Start End Blocks Id System
/dev/sda1 * 1 973 7815591 7 HPFS/NTFS
/dev/sda2 974 1040 538177+ 82 Linux swap / Solaris
/dev/sda3 1041 1648 4883760 83 Linux
/dev/sda4 1649 4864 25832520 5 Extended
/dev/sda5 1649 4864 25832488+ 83 Linux

Disk /dev/sdb: 60.0 GB, 60011642880 bytes
255 heads, 63 sectors/track, 7296 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0×000ccbfb

Device Boot Start End Blocks Id System
/dev/sdb1 1 7296 58605088+ 83 Linux

Ich habe also sda, meine Festplatte, und sdb, meine Backupplatte. sda hat 4 Partitionen. Da eine erweitert ist, werden insgesamt 5 Partitionen angezeigt. sdb hat nur eine Partition. Wenn die Festplatte und die Backupplatte die identische Größe haben und man die Backupplatte für nichts anderes braucht, kann man das Backup direkt wie hier beschrieben durchführen. Dabei gehen ALLE Daten auf der externen Platte verloren! Die externe Platte ist dann ein exakter Klon der Festplatte. Möchte man jedoch das Image in eine Datei auf der externen Platte sichern (auf der externen Platte befindliche Daten gehen hierbei nicht verloren), empfiehlt sich eine der folgenden Vorgehensweisen:

zunächst muss man sich vergewissern, dass

  • die Festplatte NICHT ins Dateisystem eingehängt ist
  • die externe Platte mit Schreibzugriff ins Dateisystem eingehängt ist

Überprüft werden kann dies mit:

mount -l

Sollte die Festplattenpartition sda1 z.B. auf /media/sda1 eingehängt sein, kann sie mit

umount /media/sda1

ausgehängt werden. Die externe Platte kann mit mount ins Dateisystem eingehängt werden (falls sie noch nicht eingehängt ist). Hierbei muss mit dem Parameter “-t” noch der Dateisystemtyp der externen Platte übergeben werden:

mount -t ext3 /dev/sdb1 /media/sdb1

oder bei ntfs Formatierung

mount -t ntfs-3g /dev/sdb1 /media/sdb1

Unkomprimiertes Backup

Ein unkomprimiertes Backup wird mit

dd if=/dev/sda of=/media/sdb1/backup.img bs=1M

erstellt. if gibt die Festplatte an, of den Speicherort und bs die Größe der Blöcke, die auf einmal kopiert werden sollen. Ich habe hier 1Megabyte gewählt. Die Wahl hat lediglich Auswirkung auf die Geschwindigkeit. Man kann ausprobieren, was am Schnellsten geht. In den Standardeinstellungen verläuft die Kopie recht langsam.

Das so entstandene Image hat exakt dieselbe Größe wie die kopierte Festplatte unabhängig davon, wie viele Daten auf der Platte sind. Ein Backup einer 40GB Platte hat also selbst auch immer genau 40GB. Somit weiß man auch, wie viel Speicher auf dem externen Datenträger frei sein muss.

Komprimiertes Backup

Um ein komprimiertes Backup zu erstellen, wird der von dd erzeugte Datenstrom von gzip komprimiert. Hierfür werden Pipes und Umleitungen verwendet.

dd if=/dev/sda bs=1M | gzip > /media/sdb1/backup.img.gz

Alternativ kann man auch mit bzip2 eine noch bessere Komprimierungsrate erreichen Vorteile und Nachteile der Varianten

Ein komprimiertes Image kann deutlich kleiner sein, besonders ein bzip2-komprimiertes Image ist kleiner als eines mit gzip, allerdings auch rechenintensiver (und damit langsamer) bei der Erstellung.

Ein unkomprimiertes Image hat den Vorteil, dass einzelne Partitionen nachträglich ins Dateisystem readonly eingehängt werden können. Man kann also auf die Daten im Backup zugreifen ohne das Backup zurückspielen zu müssen. Das geht (meines Wissens) mit einem komprimierten Image nicht. Zurückspielen eines Backups

Ein unkomprimiertes Backup lässt sich mit

dd if=/media/sdb1/backup.img of=/dev/sda bs=1M

zurückspielen. Ein komprimiertes Backup hingegen mit

gunzip -c /media/sdb1/backup.img | dd of=/dev/hda bs=1M

Einbinden eines unkomprimierten Backups

Wie oben schon angesprochen lässt sich eine Partition eines unkomprimierten Backups in das Dateisystem einbinden. Leider gibt es kein tool, das dies vollautomatisch erledigt, es ist allerdings auch kein Hexenwerk, dies von Hand zu bewerkstelligen.

Zunächst wird das gesamte Backup an das loopdevice loop0 gehängt:

losetup /dev/loop0 /media/sdb1/backup.img

Anschließend kann man mit

fdisk -ul /dev/loop0

die Partitionstabelle auslesen. Man kann natürlich auch vor dem Backup die Partitionstabelle mit diesem Befehl auslesen und abspeichern, dann erübrigt sich dieser Schritt. Meine sieht dann so aus:

Disk /dev/loop0: 40.0 GB, 40007761920 bytes
255 heads, 63 sectors/track, 4864 cylinders, total 78140160 sectors
Units = sectors of 1 * 512 = 512 bytes
Disk identifier: 0xcccdcccd

Device Boot Start End Blocks Id System
/dev/loop0p1 * 63 15631244 7815591 7 HPFS/NTFS
/dev/loop0p2 15631245 16707599 538177+ 82 Linux swap / Solaris
/dev/loop0p3 16707600 26475119 4883760 83 Linux
/dev/loop0p4 26475120 78140159 25832520 5 Extended
/dev/loop0p5 26475183 78140159 25832488+ 83 Linux

Jetzt kann das loopdevice mittels

losetup -d /dev/loop0

wieder gelöscht werden. Jetzt wird das Backup erneut über ein loopdevice angesprochen, allerdings wird losetup ein offset als Parameter übergeben. Offset bedeutet, dass losetup das Backup nun nicht mehr am Beginn des Backups einhängt, sondern irgendwo mittendrin. Die oben erhaltene Partitionstabelle ermöglicht es, den offsetparameter so zu bestimmen, dass losetup mit dem übergebenen offset genau bei der gewünschten Partition landet.

Nehmen wir mal an, ich möchte bei Partition Nummer 3 meines Backups landen. Hierfür lese ich aus der Tabelle die Anzahl an Sektoren (16707600) und multipliziere diese mit der Anzahl an bytes pro Sektor (=512). Macht insgesamt einen offset von 8554291200 bytes :-) Jetzt kann man mit

losetup -o 8554291200 /dev/loop0 /media/sdb1/backup.img

das Backup erneut über ein loopdevice ansprechen, diesmal allerdings an einer bestimmten Stelle und nicht direkt am Anfang. Wenn bis jetzt alles erfolgreich war, sollte man mit mount die entsprechende Partition einbinden können:

mkdir ~/backup
mount -t ext3 /dev/loop0 ~/backup

Status von dd anzeigen lassen

dd besitzt per default keine Statusanzeige, so dass man bei großen Datenmengen keine Informationen über die Dauer des Kopiervorgangs hat. dd reagiert jedoch auf das benutzerdefinierte Signal USR1 bzw. SIGUSR1. Startet man also einen Kopiervorgang im Hintergrund mit:

# dd if=/dev/sda of=/dev/sdb &  
[1] 8512

So hat man den Kopiervorgang im Blick und kann die ungefähre Dauer abschätzen. kann man das Signal USR1 (Signal Nummer 10) mit kill an den dd Prozess schicken:

# kill -USR1 8512  
17798625+0 Datensätze ein  
17798624+0 Datensätze aus  
9112895488 Bytes (9,1 GB) kopiert, 272,58 Sekunden, 33,4 MB/s 

So hat man den Kopiervorgang im Blick und kann die ungefähre Dauer abschätzen.