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)

  • 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