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;

openSUSE Build Service is sponsored by