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.

Für ein regelmäßiges, professionelles Backup empfiehlt sich, rsnapshot einzusetzen, wie auf der Seite BackupServer beschrieben.

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)

  • 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