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.
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 #
#!/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";
}
}
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
(Habe ich bisher nur bei Login per public key ohne Passwort getestet -- ThomasBayen)
Links #
- IBM-Artikel
gute Einführung in remote Backups per tar, insbesondere auch in die ssh-Authentifizierung
- Linuxwiki.de
hat einen guten Artikel über inkrementelle Backups mit rsync