Systembackup mit Hilfe von dd
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.