= Backup - Script =

Immer wieder kommt es vor, daß ich bestimmte Bereiche auf fernen Rechnern sichern will. Natürlich gibt es dazu ganz ausgefeilte Spezial-Programme. Meistens müssen diese aber erstmal installiert und konfiguriert werden, teilweise wird zum Sichern ein von anderen Tools nicht lesbares Format benutzt usw. Alles was ich will, ist hingegen, ein *.tgz-Archiv, wenn sich im Zielverzeichnis was geändert hat. Also habe ich eine ganz einfache Lösung geschrieben.

== Alternativen ==

* Für ein regelmäßiges, professionelles Backup empfiehlt sich, [http://rsnapshot.org rsnapshot] einzusetzen, wie auf der Seite BackupServer beschrieben. '''rsnapshot ist wohl unter Linux die beste Lösung, wenn man regelmäßig automatisierte, inkrementelle Backups auf eine Festplatte machen will, die im Notfall sofort einsatzbereit sind.''' -- ThomasBayen

* Nach einem online verfügbaren Artikel im [Linux User Magazin 02/2007|http://www.linux-user.de/ausgabe/2007/02/058-mondo/index.html] kann ich auch das Gespann [Mondo+Mindi|http://www.mondorescue.org/] zur Datensicherung mit grafischer (NCurses-)Oberfläche empfehlen. \\Dabei danke ich Thomas Bayen für die Hilfe zum Thema [NFS|http://de.wikipedia.org/wiki/Network_File_System] unter DisklessClient. (Das Stichwort ''nfs-kernel-server'' wollte mir partout nicht einfallen.) --MarkusMonderkamp am 05.02.2007

:: '''Mondo ist wohl eine gute Lösung, wenn man ab und zu Sicherungen seines Basissystems auf CD (und zwar auch zur Komplettwiederherstellung) machen will. Es kann u.a. eine bootfähige Installations-CD erzeugen.''' -- ThomasBayen

== ssh-Zugang ==

Zuerstmal muss unser Skript sich ja überhaupt in den fernen Rechner
einloggen können,
um dort Dateien sichern zu können. Damit das automatisch, d.h. ohne
Passworteingabe
funktioniert, benutzen wir RSA-Keys.

Zuerst muss auf dem SSH-Client (also dem Backup-Server) ein
RSA-Schlüsselpaar erzeugt
werden. Dies geschieht mit ''ssh-keygen -t rsa''. Wir benutzen
damit einen SSH2-RSA-Key.
Eine Passphrase geben wir nicht ein, da wir ja automatisch
zugreifen wollen.

Auf dem fernen Server (wo die Backup-Daten liegen) muss nun ein
Benutzer ausgewählt
werden, der Zugang zu den zu sichernden Daten hat. Zu beachten ist
jedoch, daß ein
Angreifer, der den Backup-Server erobert, auch Zugriff auf diesen
Account hat, da ja nun
ein Passwort-loser Zugang vom Backup-Server aus möglich ist. Also
sollte man nicht root
auswählen, sondern besser einen besonderen User anlegen, der nur
Lesezugriffe im System 
hat.

Nun wird die Datei ''~/.ssh/id_rsa.pub'' auf den fernen Server in
die Datei 
''~/.ssh/authorized_keys'' kopiert (bzw. angehängt, wenn da bereits
Schlüssel drin sind). Damit ist der SSH-Zugang erlaubt.

== Vorbereitung ==

Am besten loggt man sich jetzt testweise mit '''ssh
username@servername''' in den fernen Rechner
ein. Klappt das ohne Passwort, kann man sofort ein Verzeichnis
"backup" anlegen. Hier wird später
das jeweils aktuelle tgz-Archiv angelegt. (Falls das
Homeverzeichnis des Benutzers gesichert
werden soll, darf das backup-Verzeichnis natürlich nicht
mitgesichert werden. Dann sollte der
Quelltext geändert werden und z.B. /tmp für das Backup genommen
werden.

== Backup-Script konfigurieren ==

Jetzt muss nur noch für jedes zu sichernde Verzeichnis eine Zeile
im Script angelegt werden.
Danach das Verzeichnis für die Backup-Dateien ''backupdir'' anlegen
und wie oben im Quelltext 
angegeben das Script per Cronjob z.B. täglich starten.

Die Einstellung für die SSH-Parameter sollte auf ''-2'' für das
SSH2-Protokoll stehen, der tar-Parameter
auf ''-j'' für bzip2-Kompression. Einzig für den Zugriff auf
Sourceforge sind andere Werte nötig,
da dort nicht die alerneuesten ssh- bzw. tar-Versionen benutzt
werden.

''Update: Der Ärger mit den alten Programmversionen bei Sourceforge
ist vorbei, seitdem die die Shell-Server neu aufgesetzt haben. Also
kann hier auch -2 und -j benutzt werden. -- ThomasBayen''

== Script-Quelltext ==

<pre>
#!/usr/bin/perl
# backup.pl
# Script f|r automatisches Backup
#
# Dieses Script sollte mit forgender Crontab gestartet werden:
#




----------------------------------------------------------------------
# MAILTO=tbayen@bayen.loc
# @midnight /usr/bin/perl
/home/tbayen/perl/Backup-Manager/backup.pl
#
----------------------------------------------------------------------


use warnings;
use diagnostics;
use strict;


# Parameter
###########

my @quellen=(
  [qw(nevent_cgibin    -2 readuser nevent.pommes.loc     -j
/usr/lib/cgi-bin/)],
  [qw(nevent_eventdata -2 readuser nevent.pommes.loc     -j
/var/eventmanager/)],
  [qw(nevent_wiki      -2 readuser nevent.pommes.loc     -j
/var/wiki/)],
  [qw(empire_wiki      -1 tbayen   shell.sourceforge.net -I
empire/wiki/)],
  [qw(lug_wiki         -1 tbayen   shell.sourceforge.net -I
lug-kr/wiki/)],
);
my $ziel='/home/tbayen/perl/Backup-Manager/backupdir';



foreach my $quelle(@quellen){
 
my($projekt,$parameter,$user,$server,$tarparam,$verzeichnis)=@{$quelle};

  # Hilfsvariablen werden erzeugt:
  my $backupfile="backup/${projekt}_daily.tar.bz2";
  # Ich benutze bzip2, weil es gut komprimiert. Ausserdem sind zwei
  # zip-Archive f|r md5 nicht identisch (ein Byte unterscheidet
sich).
  # Leider ist der Befehl hierfuer nicht bei jedem tar gleich. :-(
  $tarparam.=' -c';
  $tarparam.=' -C /' if $verzeichnis =~ s/^\///;

  # Tar-File erzeugen und Checksumme holen:
  my $output=`ssh $parameter $user\@$server 'tar $tarparam -f
$backupfile $verzeichnis && md5sum $backupfile'`
  unless($output){
    print "Fehler beim Zugriff auf den Server!\n";
    next;
  }

  my $checksum='';
  if(open FILE,"<$ziel/${projekt}_checksum"){
    $checksum=<FILE>;
    close FILE;
  }
  # Wenn sich die Checksumme gedndert hat, wird die Datei geholt
  if($checksum ne $output){
    # Datum soll mit in den Dateinamen, muss also erstmal berechnet
werden
    my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);
    my $time=($year+1900).($mon+1).$mday;
    system "scp $parameter -q $user\@$server:$backupfile
$ziel/${projekt}_$time.tar.bz2";
    # Ldnge speichern, damit Dnderungen beim ndchsten Mal erkannt
werden:
    open FILE,">$ziel/${projekt}_checksum";
    print FILE $output;
    close FILE;
    print "Projekt $projekt gesichert.\n";
  }
}
</pre>



== schnelles Backup zwischendurch ==

Wer nur mal schnell ein einzelnes anständiges Backup übers Netz machen will, kann einen Befehl wie den folgenden benutzen:

  ssh root@meinserver 'tar cz /home/' >meinserver-home-$(date+%Y%m%d-%H%M%S).tgz

Wer eine grosse Datei (z.B. ein Image) möglichst schnell per ssh kopieren möchte, kann das mit

  tar cSC /source/dir/ filename | ssh -c blowfish username@zielhost 'tar xSC /target/dir'

machen. Im LAN ist es meiner Erfahrung nach schneller, auf Kompression zu verzichten. Gerne würde ich manchmal auch auf Verschlüsselung verzichten (die einzige ordentliche mir bekannte Methode geht mit netcat), habe aber damit bisher noch nicht viel experimentiert. Einen interessanten Geschwindigkeitsvergleich habe ich unter http://www.spikelab.org/blog/scpTarSshTarNc.html gefunden. Fazit: Niemals scp benutzen, immer komprimieren. Letztere Aussage wage ich zu relativieren, wenn man einen anderen Prozessor oder mehr als die 100MBit-Leitung des Autors benutzt.

Wer ein ganzes System sichern will (nicht nur das Home-Verzeichnis, kann das laut http://linuxclues.blogspot.com/2007/07/backup-your-system-using-tar.html mit folgendem Befehl machen

  sudo tar cvzpf /home/Backup.tgz --same-owner --exclude=/home/Backup.tgz --exclude=/home/error.log --exclude=/proc/* --exclude=/media/* --exclude=/dev/* --exclude=/mnt/* --exclude=/sys/* --exclude=/tmp/* / 2>/home/error.log

Eine weitere Möglichkeit ist die Übertragung mit rsync. Es hat ein paar Vorteile vor allem bei sehr grossen Dateien (z.B. Imagedateien von virtuellen Systemen): Es komprimiert selbst (besser als ssh), es kann mit sparse-Dateien umgehen und es kann abgebrochene Transfers wieder aufnehmen. Außerdem erlaubt es die Angabe eines Bandbreitenlimits, damit bei einem langen Backup nicht das ganze Netz blockiert ist. Beispiel:

  rsync -avzrS --partial --bwlimit=50000 root@meinserver:/home/virtual/.VirtualBox/HardDisks/serverimage.vdi /home/virtual/backups/



== Backup auf CD/DVD ==

''schamlos aus der DLUG-Mailingliste extrahiert, dank an T. Reinartz, Mail vom 13.11.2008 um 21.33 Uhr''

__Ziel:__ Sicherung eines Dateisystems < 4,4 GB mit Hard- und Symlinks.\\
__Howto:__ \\
# Eine Datei erstellen, die so groß wie eine CD (DVD) ist
# Diese Datei mit ext2 formatieren
# Die Datei einbinden (mount)
# In die “Datei” reinschreiben, was man später auf CD\\(DVD) haben möchte
# Die “Datei” aushängen (unmont)
# Die Datei brennen (wie ein ISO-Image)
# Dann die CD (DVD) wieder einhängen und schwupps: CD mit ext2!

__Konsolenlog:__

Und technisch geht das für eine DVD so:

{{{
dd if=/dev/zero of=dvd.ext2 bs=4096 count=1024k

# Es kommt die Frage ... kein spezielles Block-Gerät ... 
# Mit ja beantworten
mke2fs  -b 4096  dvd.ext2

mkdir /mnt/ext2
mount -t ext2 -o loop=/dev/loop0 dvd.ext2 /mnt/ext2
}}}

Jetzt kann man in /mnt/ext2 scheiben. Anschließend das Einhängen wieder rückgängig machen und die Datei brennen: 

{{{
umount /mnt/ext2
# Brennen z. B. mit cdrecord oder Brasero
}}}

Diese DVD wird nach dem Einlegen (unter Ubuntu) nicht automatisch erkannt (es gibt sogar eine Fehlermeldung). Das Einhängen muss manuell erfolgen:

mount -r -t ext2 /dev/scd1 /mnt/ext2

Aber dann ist es cool. Die DVD hat in meinem Fall den ganzen Backup-Baum mit allen hard links. Und das browsen im Baum ist viel, viel schneller als in einem tar file.

Damit habe ich meine Lösung, wie ich meinen Dateibaum mit meinen backups dauerhaft sichern und ohne großen Aufwand nach alten Dateiständen suchen kann. 

== Ergänzung mit LUKS ==
''schamlos aus der DLUG-Mailingliste extrahiert, dank an H. Zessel, Mail vom 13.11.2008 um 23.30 Uhr''

Bei Debian Etch klappt das sogar, wenn das Medium ein LUKS Image hat.
Fand ich sehr praktisch.

Da man ja zu Sicherheit immer meist mit der Waffe zwingen muss, habe ich
mal meine LUKS Befehlskette hervorgeholt, die ich hinterlegen musste. 
Die tippe ich nicht aus dem Kopf. Wenigstens nicht den LuksFormat..

Nach dem Imagebauen mit dd gehts dann so weiter:

{{{
losetup /dev/loop/1  $PWD/dvd.ext2  # manchmal ziehe ich absolute Pfade vor...
                  # evtl steht der nachher irgendwo zum Nachlesen (losetup -a)

cryptsetup  -v luksFormat -c aes-cbc-essiv:sha256 -h sha1 -s 256 /dev/loop/1
}}}

Dann GROSSES YES eingeben (oder -q Option).
Dann Passphrase zweimal.
(ich habe das auch schon mal 3x machen muessen, weil ich einfach
nicht willens oder in der Lage war, GROSSES YES zu lesen
und umzusetzen  ! LOL  Er sagt das naemlich explizit ! )

Hier dann mal zur Kontrolle und spaeterem Vergleich ein 

{{{
  dmsetup ls

cryptsetup  -v luksOpen /dev/loop/1 dvd.ext2_crypt
Enter LUKS passphrase:
key slot 0 unlocked.
Command successful.

  dmsetup ls
}}}

...muesste jetzt ein dvd.ext2_crypt enthalten...

Und jetzt kommst Du wieder mke2fs, dann aber mit  /dev/mapper/dvd.ext2_crypt
..._crypt ist einfach nur ne sinnvolle Konvention. 

Wenn die automatische Erkennung nicht klappt (ich habe da auch noch einen Gentoo
Abkömmling am Laufen, der das nicht kann - zumindest nicht mit Luks), dann
kann man das pmount Kommando aber auch leicht manuell einsetzen.
Also zB   pmount /dev/dvd  BACKUP_4711

Und dann kommt eine Passphraseabfrage per X Dialog.

Wenn Du beim mke2fs oder e2label einen sinnvollen Namen angibst, so landet
das Ding ohne LUKS dann gleich beim mount in /media/BACKUP_4711.
Das machts bei LUKS leider nicht automatisch - wenigstens nicht bei Etch.
Da ist manuelles pmount von Vorteil wie oben im Beispiel.
Vielleicht hast Du ja doch mal Nerv, das zu probieren :-).
Es faellt nachher kaum noch auf. Meine mobilen Platten sind alle so.
Wenn ich sie anhaenge - Passphrase, fertig.

== Links ==

* [http://www-106.ibm.com/developerworks/linux/library/l-backup/?ca=dgr-lnxw16Backup IBM-Artikel] gute Einführung in remote Backups per tar, insbesondere auch in die ssh-Authentifizierung
* [http://www.linuxwiki.de/rsync/SnapshotBackups Linuxwiki.de] hat einen guten Artikel über inkrementelle Backups mit rsync

[{Tag Backup}]