File rsync_backup.pl of Package rsync-backupscript
#!/usr/bin/perl
use warnings;
use strict;
use Getopt::Std;
use Config::Simple;
use File::Rsync;
use File::Path;
# Parameter einlesen
my %opts;
getopts('c:m:h', \%opts) or usage();
if ($opts{h} || !$opts{c})
{
usage();
}
my @MailText;
my %ClientConfig;
Config::Simple->import_from($opts{c}, \%ClientConfig);
## send mails to:
#my $sendmailto = "ops-services\@suse.de";
my $sendmailto="";
my $lockfile = $ClientConfig{workdir}."/.rsync_backup.lock";
my $logfile = $ClientConfig{workdir}."/.rsync_backup.log";
my $send_nsca="/usr/bin/send_nsca";
my $send_nsca_cfg="/etc/nagios/send_nsca.cfg";
my $nagioshost="localhost";
# Hauptkonfiguration einlesen:
#my %MainConfig;
#my $main_config_file;
#if ($opts{m})
#{
# $main_config_file = $opts{m};
#}
#else {
# $main_config_file = "/etc/rsync_backup/main.cfg";
#}
#test ob datei lesbar
#Config::Simple->import_from($main_config_file, \%MainConfig);
my $TIMESTAMP=qx(date +%Y%m%d%H%M);
chomp($TIMESTAMP);
sub usage
{
print "Usage has to be written...\n";
exit 1;
}
printf "workdir: $ClientConfig{workdir}\nmaxbackups: $ClientConfig{maxbackups}\nserver: $ClientConfig{server}\n";
sub preparation
{
use vars qw(@MailText);
use vars qw(%ClientConfig);
my $state = 1;
if (!$ClientConfig{workdir})
{
push(@MailText, "Error in configuration: workdir not set!");
$state = -1;
}
if (! (-w $ClientConfig{workdir}))
{
push(@MailText, "Error in configuration: workdir is not writeable!");
$state = -1;
}
if (!$ClientConfig{maxbackups})
{
push(@MailText, "Error in configuration: maxbackups is not set!");
$state = -1;
}
if (!$ClientConfig{server})
{
push(@MailText, "Error in configuration: server is not set!");
$state = -1;
}
if (!$ClientConfig{module})
{
push(@MailText, "Error in configuration: module is not set!");
$state = -1;
}
if (!defined($ClientConfig{user}))
{
push(@MailText, "Error in configuration: user not set!");
$state = -1;
}
if (!defined($ClientConfig{archive}))
{
push(@MailText, "Error in configuration: archive not set!");
$state = -1;
}
if (!defined($ClientConfig{'delete'}))
{
push(@MailText, "Error in configuration: delete not set!");
$state = -1;
}
if (!defined($ClientConfig{compress}))
{
push(@MailText, "Error in configuration: compress not set!");
$state = -1;
}
if (!defined($ClientConfig{hardlinks}))
{
push(@MailText, "Error in configuration: hardlinks not set!");
$state = -1;
}
if (!defined($ClientConfig{linked}) || $ClientConfig{linked} eq "")
{
push(@MailText, "Error in configuration: linked not set!");
$state = -1;
}
if (!defined($ClientConfig{acls}))
{
push(@MailText, "Error in configuration: acls not set!");
$state = -1;
}
if (!defined($ClientConfig{'numeric-ids'}))
{
push(@MailText, "Error in configuration: numeric-ids not set!");
$state = -1;
}
if (!defined($ClientConfig{subdir}))
{
$ClientConfig{subdir} = "";
}
if (!defined($ClientConfig{exclude}))
{
$ClientConfig{exclude} = "";
}
if (!-d $ClientConfig{workdir})
{
mkdir($ClientConfig{workdir}) or push(@MailText, "Error, could not create $ClientConfig{workdir}");
$state = -1;
}
return $state;
}
sub find_oldest
{
use vars qw(%ClientConfig);
use vars qw(@MailText);
my $oldest;
opendir(WORKDIR, $ClientConfig{workdir});
while ( my $currentDir = readdir(WORKDIR))
{
$currentDir = $ClientConfig{workdir}."/".$currentDir;
if ( $currentDir eq $ClientConfig{workdir}."/." || $currentDir eq $ClientConfig{workdir}."/.." )
{
next;
}
if (!$oldest)
{
$oldest = $currentDir;
}
if ((-e $currentDir."/.last_synced"))
{
if (-e $oldest."/.last_synced"){
if ((stat($oldest."/.last_synced"))[9] > (stat($currentDir."/.last_synced"))[9] )
{
$oldest = $currentDir;
}
}
}
else {
push(@MailText, "find_oldest: $currentDir./.last_synced not found.\nThis directory will be ignored!\n");
}
}
closedir(WORKDIR);
return $oldest;
}
sub find_latest
{
use vars qw(%ClientConfig);
use vars qw(@MailText);
# my $newest;
my @newest=qw();
opendir(WORKDIR, $ClientConfig{workdir});
while (my $currentDir = readdir(WORKDIR))
{
$currentDir = $ClientConfig{workdir}."/".$currentDir;
if ( $currentDir eq $ClientConfig{workdir}."/." || $currentDir eq $ClientConfig{workdir}."/.." || !-d $currentDir)
{
next;
}
if (!$#newest) # $newest is empty, set it to the current dir
{
unshift @newest,$currentDir;
}
if ((-e $currentDir."/.last_synced"))
{
if ((stat($newest[0]."/.last_synced"))[9] < (stat($currentDir."/.last_synced"))[9] ) # $newest is older than the current dir..
{
# $newest = $currentDir; # .. set $newest to the current dir
unshift @newest,$currentDir;
}
} else {
push(@MailText, "find_latest: $currentDir/.last_synced not found.\nThis directory will be ignored!\n");
}
}
closedir(WORKDIR);
# return $newest;
return \@newest;
}
sub count_backups
{
use vars qw(%ClientConfig);
my $counted = 0;
opendir(WORKDIR, $ClientConfig{workdir});
while ( my $currentDir = readdir(WORKDIR))
{
if ( $currentDir eq "." || $currentDir eq "..")
{
next;
}
$counted++;
}
closedir(WORKDIR);
return $counted;
}
sub delete_oldBackups
{
while ($ClientConfig{maxbackups} < count_backups())
{
my $oldest = find_oldest();
# print "deleting ", $oldest ,"\n";
rmtree($oldest,{ verbose=> 0, error => \my $err_list });
push (@MailText, "\ndelete_oldBackups:\ndeleted: $oldest \nErrors:\n", @$err_list);
}
}
sub do_backup
{
use vars qw(@MailText);
use vars qw($TIMESTAMP);
use vars qw($lockfile);
use vars qw(%ClientConfig);
#create lockfile
open(LOCKFILE, ">", $lockfile);
print LOCKFILE $TIMESTAMP;
close(LOCKFILE);
my $counted_backups = count_backups();
$ENV{'USER'} = $ClientConfig{user};
$ENV{'RSYNC_PASSWORD'} = $ClientConfig{passwd};
my $obj;
my %RsyncOptions = ('archive' => $ClientConfig{archive},
'compress' => $ClientConfig{compress},
'delete' => $ClientConfig{'delete'},
'acls' => $ClientConfig{acls},
'numeric-ids' => $ClientConfig{'numeric-ids'},
'debug' => 6,
'verbose' => 5,
'hard-links' => $ClientConfig{hardlinks},
'rsync-path' => '/usr/bin/rsync');
if ($ClientConfig{linked} && $counted_backups > 0)
{
# $RsyncOptions{'link-dest'} = find_latest();
}
if ($ClientConfig{exclude} ne "")
{
my @exclude_Array = split(/ /, $ClientConfig{exclude});
$RsyncOptions{exclude} = \@exclude_Array;
}
$obj = File::Rsync->new(%RsyncOptions);
if (mkdir($ClientConfig{workdir}."/".$TIMESTAMP))
{
if ($ClientConfig{subdir} eq "")
{
$obj->exec( { src => $ClientConfig{server}."::".$ClientConfig{module},
dest => $ClientConfig{workdir}."/".$TIMESTAMP."/" } ) or push (@MailText, "rsync failed\n");
} else {
my @subdirs = split(/ /,$ClientConfig{subdir});
foreach (@subdirs)
{
push (@MailText, "synced subdir: $_");
$obj->exec( { src => $ClientConfig{server}."::".$ClientConfig{module}."/".$_,
dest => $ClientConfig{workdir}."/".$TIMESTAMP."/" } ) or push (@MailText, "rsync failed\n");
}
}
my @aref = $obj->err;
if (@aref)
{
push (@MailText, "ERROR:\ndo_backup: ", @aref);
}
push (@MailText, $obj->lastcmd);
open(LASTSYNCED, ">",$ClientConfig{workdir}."/".$TIMESTAMP."/.last_synced");
print LASTSYNCED $TIMESTAMP;
close(LASTSYNCED);
} else {
push(@MailText, "do_backup: ERROR, unable to mkdir $ClientConfig{workdir}."/".$TIMESTAMP\n");
}
#remove lockfile
unlink($lockfile);
return $obj->status;;
}
# let the script beginn...
my $rsync_state;
my ($starttime, $backupendtime, $endtime);
if (preparation() == 1)
{
if (!(-e $lockfile))
{
$starttime = time;
$rsync_state = do_backup();
$backupendtime = time;
if ($rsync_state != 1)
{
delete_oldBackups();
}
$endtime = time;
} else {
print "lockfile $lockfile exists, no backup done!\n";
push (@MailText, "lockfile exists, no backup done!");
$rsync_state = -1;
}
} else {
$rsync_state = -1;
}
my $subject;
if ($rsync_state != 0 )
{
$subject = "Backup failed on $ClientConfig{server} $ClientConfig{module}";
} else {
$subject = "Backup done on $ClientConfig{server} $ClientConfig{module}";
}
my $mailprog = '/usr/sbin/sendmail';
if ("$sendmailto" ne ""){
open (MAIL, "|$mailprog $sendmailto");
print MAIL ("From: rsync_backup.pl\n");
print MAIL ("Subject: $subject\n\n");
print MAIL "Synced server: $ClientConfig{server} with module: $ClientConfig{module} to $ClientConfig{workdir}/$TIMESTAMP\n";
if (defined($starttime))
{
my $timevalue = $backupendtime - $starttime;
print MAIL "Backup duration: $timevalue seconds \n";
$timevalue = $endtime - $backupendtime;
print MAIL "Delete duration: $timevalue seconds \n";
}
for (my $i = 0; $i < @MailText; $i++)
{
print MAIL $MailText[$i], "\n";
}
close (MAIL);
}
if ("$logfile" ne ""){
open(LOG,">>$logfile") or die "Could not open $logfile: $!\n";
print LOG localtime()." synced server: $ClientConfig{server} with module: $ClientConfig{module} to $ClientConfig{workdir}/$TIMESTAMP\n";
if (defined($starttime))
{
my $timevalue = $backupendtime - $starttime;
print LOG localtime()." backup duration: $timevalue seconds \n";
$timevalue = $endtime - $backupendtime;
print LOG localtime()." delete duration: $timevalue seconds \n";
}
if (defined($ClientConfig{'nsca'})){
open(SEND,"| $send_nsca -H $nagioshost -c $send_nsca_cfg") or warn ("Could not send to nagios via NSCA!\n");
print SEND "fermi\tBackup status\t0\tSynced server: $ClientConfig{server} to $ClientConfig{workdir}/$TIMESTAMP";
close(SEND);
print "fermi\tBackup status\t0\tSynced server: $ClientConfig{server} to $ClientConfig{workdir}/$TIMESTAMP";
}
close(LOG);
}
#$rsync_state;