blog.bartlweb - a technologist's external brain

Perl-Skript für überwachte Backups mit Hilfe von rsync

Das folgende Perl-Skript holt sich Verzeichnisse via rsync über SSH von einen entfernten Linux-Rechner und sichert diese lokal. Konfigurieren lässt sich dabei der Remote-Host und die zu sichernden Verzeichnisse sowie die Benachrichtigung via E-Maill. Das Skript lässt sich per Cronjob aufrufen und sendet nur im Falle eines Fehlers ein E-Mail.

Dateien von einem Remote-System sichern

#!/usr/bin/perl
 
#
# config
#
 
$remotehost = "192.168.0.1";
$remoteport = "22";
$remoteuser = "username";
 
$subject = "Backup: rsync error";
$mailfrom = "backup\@domain.com";
$mailto = "admin\@domain.com";
 
$tmp_file = "/tmp/backup.txt";
 
# remotepath => localpath
%rsync = (
   '/etc/' => '/mnt/backup/etc/',
   '/mnt/data/' => '/mnt/backup/data/'
);
 
$rsync_args = '-avze';
$rsync_options = '--delete --hard-links --human-readable';
 
#
# script
#
 
use FileHandle;
use POSIX qw/strftime/;
 
while( ($remotepath, $localpath) = each(%rsync) ){
   $starttime = strftime('%T (%d.%m.%Y)', localtime);
   @check = system('rsync ' . $rsync_args . ' "ssh -p ' . $remoteport . ' -l ' . $remoteuser . ' -o ServerAliveInterval=5" ' . $rsync_options . ' ' .  $remotehost . ':' . $remotepath . ' ' . $localpath . ' >> ' . $tmp_file . ' 2>&1');
 
   if($? != 0) {
       push(@warn, "$remotepath => $localpath");
       $endtime = strftime('%T (%d.%m.%Y)', localtime);   
       push(@warn, "     $starttime - $endtime\n");
       system('echo ------------------------ >> ' . $tmp_file);
   }
}
 
if(@warn){
   $mail = new FileHandle;
   $mail->open("| /usr/sbin/sendmail -t") || die "Cannot open: $!";
   $mail->print("From: $mailfrom\n");
   $mail->print("To: $mailto\n");
   $mail->print("Subject: $subject\n\n");
 
   foreach (@warn) {
       $mail->print($_, "\n");
   }
 
   $mail->print("\n\n------------------------\n\n");
 
   open(HANDLE, $tmp_file);
   while (<HANDLE>){
        $mail->print($_, "\n");
   }
   close(HANDLE);
 
   $mail->close();
}
 
system('rm ' . $tmp_file);

Dateien vom lokalen Rechner wegsichern

Sollten Sie den umgekehrten Fall benötigen, dass Sie lokale Verzeichnisse via SSH auf einen entfernten Rechner sichern müssen, dann bietet sich folgende Abwandlung des oberen Skriptes an.

#!/usr/bin/perl
 
#
# config
#
 
$remotehost = "192.168.0.1";
$remoteport = "22";
$remoteuser = "username";
 
$subject = "Backup: rsync error";
$mailfrom = "backup\@domain.com";
$mailto = "admin\@domain.com";
 
$tmp_file = "/tmp/backup.txt";
 
# localpath => remotepath
%rsync = (
   '/etc/' => '/mnt/backup/etc/',
   '/mnt/data/' => '/mnt/backup/data/'
);
 
$rsync_args = '-avze';
$rsync_options = '--delete --hard-links --human-readable';
 
#
# script
#
 
use FileHandle;
use POSIX qw/strftime/;
 
while( ($localpath, $remotepath) = each(%rsync) ){
   $starttime = strftime('%T (%d.%m.%Y)', localtime);
   @check = system('rsync ' . $rsync_args . ' "ssh -p ' . $remoteport . ' -l ' . $remoteuser . ' -o ServerAliveInterval=5" ' . $rsync_options . ' ' . $localpath . ' ' . $remotehost . ':' . $remotepath . ' >> ' . $tmp_file . ' 2>&1');
 
   if($? != 0) {
       push(@warn, "$localpath => $remotepath");
       $endtime = strftime('%T (%d.%m.%Y)', localtime);   
       push(@warn, "     $starttime - $endtime\n");
       system('echo ------------------------ >> ' . $tmp_file);
   }
}
 
if(@warn){
   $mail = new FileHandle;
   $mail->open("| /usr/sbin/sendmail -t") || die "Cannot open: $!";
   $mail->print("From: $mailfrom\n");
   $mail->print("To: $mailto\n");
   $mail->print("Subject: $subject\n\n");
 
   foreach (@warn) {
       $mail->print($_, "\n");
   }
 
   $mail->print("\n\n------------------------\n\n");
 
   open(HANDLE, $tmp_file);
   while (<HANDLE>){
        $mail->print($_, "\n");
   }
   close(HANDLE);
 
   $mail->close();
}
 
system('rm ' . $tmp_file);

Dateien/Ordner aus der Synchronisierung ausnehmen

Um Dateien oder Ordner aus der Synchronisierung auszunehmen müssen Sie zunächst eine Text-Datei mit den Ausnahmen (eine Ausnahme pro Zeile) erstellen. Die Ausnahme-Regel besteht dabei aus dem lokalen Pfad zur Datei bzw. zum Ordner. Für Mehrfachausnahmen wird der Wildcard-Operator unterstützt.

Das folgenden Beispiel wird den Inhalt des Ordners download, den Ordner test bzw. die Datei resolv.conf bei der Synchronisierung ausnehmen.

srv/www/htdocs/download/*
mnt/data/test
etc/resolv.conf

Damit unsere Ausnahmen auch berücksichtigt werden müssen Sie in den obigen Skripten die Zeile mit den rsync-Options wie folgt abändern. Vergessen Sie nicht den Pfad zu Ihrer Ausnahmedatei entsprechend anzupassen.

$rsync_options = '--delete --hard-links --human-readable --exclude-from "/my/path/backup_exclude.txt"';

Dieser Artikel hat Dir deinen Tag gerettet?

... und mühevolles Probieren, Recherchieren und damit Stunden an Zeit gespart? Oder einfach nur Dein Problem gelöst?

Dann würde ich mich freuen, wenn Du meine Zeit für die Erstellung dieses Blogartikels mit einer kleinen Anerkennung honorierst:

Zahlung mit PayPal oder Kreditkarte.

Hinweis zur Verwendung

Die Übermittlung einer Zahlung ist eine persönliche Anerkennung Ihrerseits an den Entwickler (Christian Bartl, Privatperson). Eine Zahlung ist nicht zweckgebunden und es ist keine Gegenleistung zu erwarten. Bitte beachten Sie, dass für eine übermittelte Zahlung keine Quittung ausgestellt werden kann.

Über den Autor

Christian Bartl

Christian Bartl Requirements Engineer
& Solution Architect für Online und Mobile

Als Technologie-Enthusiast und begeisterter Programmierer entwickle ich in meiner Freizeit Websites, Software und IT-Lösungen, die mir selbst und anderen den Alltag vereinfachen.

mehr auf christian.bartl.me

Kommentare

Kommentar schreiben

Der hier angegebene Name wird gemeinsam mit deinem Kommentar auf der Website veröffentlicht.

Deine E-Mail-Adresse wird zur einmaligen Benachrichtigung bei Veröffentlichung des Kommentars genutzt.

Benachrichtigung per E-Mail über Antworten auf meinen Kommentar erhalten.

Bitte tippe die Zahlenkombination "2755" ein, nur dann kann ich deinen Kommentar entgegennehmen.

Bitte fülle dieses Feld nicht aus, nur dann kann ich deinen Kommentar entgegennehmen.