-
-
Save maugsburger/0f27031978487e4447194641213ee50d to your computer and use it in GitHub Desktop.
dyplyreport.pl - a duply syslog wrapper. This script runs duply (a duplicity backup wrapper), filters all the bias and writes all important information into syslog.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
# vi: sw=4 ts=4 et | |
# (C) 2011 Dirk Ruediger <dirk@niebegeg.net> | |
# (C) 2013 Moritz Augsburger | |
# Feel free do hack or adopt it! | |
# | |
# A syslog wrapper for duply. It runs duply for multiple profiles, | |
# filers "bias" out and writes all important and unexpected messages to syslog. | |
# | |
# One mail for all profiles together is generated. | |
# | |
# usage: | |
# Like duply. all arguments are passed to duply | |
# | |
# duplyreport.pl [--syslog|-s] [--mail|-m=<mailto>] -p profilename1 [-p profilename2 [-p…]] duply arguments | |
# | |
# etc. | |
# The script should not produce any output to console. | |
use warnings; | |
use strict; | |
use Getopt::Long qw(:config pass_through); | |
use Date::Format; | |
use Sys::Hostname; | |
my $procname = 'duply'; | |
my $state = 'nostate'; | |
my $buffer = ''; | |
my $mailto = ''; | |
my $syslog = 0; | |
my @profiles; | |
my $mail_content = ''; | |
my @mail_parts; | |
my $msg; | |
my $errorcount = 0; | |
my $result = GetOptions ( | |
"syslog|s" => \$syslog, | |
"mail|m=s" => \$mailto, | |
"profile|p=s" => \@profiles, | |
); | |
my $timestr = time2str('%c', time); | |
if( $syslog ) { | |
use Unix::Syslog qw(:subs :macros); | |
openlog "duply", LOG_PID | LOG_INFO, LOG_LOCAL0; | |
} | |
if( $mailto ne '' ) { | |
if ($mailto !~ m/^[A-Za-z0-9](([_\.\-\+]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$/) { | |
my $message = "Invalid mail address format: $mailto"; | |
$mailto = ''; | |
logger('error', $message); | |
exit 1; | |
} else { | |
use MIME::Lite; | |
} | |
} | |
sub logger { | |
my $level = shift || 'info'; | |
my $message = shift || ''; | |
if ($syslog) { | |
my $loglevel = LOG_INFO; | |
if ($level ne 'error') { | |
$loglevel = LOG_ERR; | |
} | |
syslog($loglevel, $message); | |
} | |
if ($mailto ne '') { | |
$mail_content .= uc($level). " $message\n"; | |
} | |
} | |
sub sendmail { | |
return if $mailto eq ''; | |
$msg = MIME::Lite->new( | |
To => $mailto, | |
Type =>'TEXT', | |
Data => $mail_content, | |
); | |
if ( $errorcount > 0 ) { | |
$msg->add('Subject', "Duply report ".$timestr." on ".hostname().": $errorcount ERRORS"); | |
} else { | |
$msg->add('Subject', "Duply report ".$timestr." on ".hostname().": ALL OK"); | |
} | |
$msg->attach($_) foreach( @mail_parts ); | |
$msg->send(); | |
} | |
sub mydie { | |
$msg = @_; | |
logger( 'error', $msg ); | |
$errorcount++; | |
sendmail(); | |
die $msg; | |
} | |
if( @profiles < 1 ) { | |
mydie("No profiles to run specified"); | |
} | |
foreach (@profiles) { | |
my $proc; | |
my $profile = $_; | |
my $mail_proc_content = ''; | |
my @myduplyarg; | |
push @myduplyarg, $profile, @ARGV; | |
my $localerrorcount = 0; | |
unless (open($proc, "LC_ALL=C $procname @myduplyarg 2>&1 |")) { | |
logger('error', "Could not start $procname @myduplyarg process: $!"); | |
$localerrorcount++; | |
next; | |
} | |
while (<$proc>) { | |
$mail_proc_content .= $_; | |
chomp; | |
$localerrorcount++ if /FAILED/; | |
next if | |
/^(Using|Autoset|Test -|Cleanup -|Deleting local) / || | |
/^Skipping n\/a script / || | |
/^Reading globbing filelist / || | |
/^Synchronizing remote metadata to local cache/ || | |
/^Local and Remote metadata are synchronized, no sync needed/ || | |
/^Generating delta - (new|deleted|changed) file/ || | |
/^-+\[ Backup Statistics \]-+/ || | |
/^gpg: Signature made / || | |
/^NcFTP version is [0-9.]+/ || | |
/^(StartTime|EndTime|ElapsedTime|SourceFiles|NewFileSize|ChangedFileSize|ChangedDeltaSize|DeltaEntries|RawDeltaSize|Errors) [0-9.]+/ || | |
/^WARNING:$/ || | |
/^(Duplicity version '[0-9.]+' does not support providing the password as|env var for rsync backend. For security reasons you should consider to|update to a version greater than '[0-9.]+' of duplicity.)/ || | |
/^Verify complete: \d+ files compared, 0 differences found/ || | |
/^Copying duplicity\S* to local cache/ || | |
/^Skipping n\/a script '\S+\/(pre|post)'\./ || | |
/^Running '\/\S+\/(pre|post)' - OK/ || | |
/File descriptor.*leaked on lvcreate invocation\./ || | |
/Logical volume ".*" (created|successfully removed)/; | |
s/^--- //; | |
s/ at [0-9:.]+ - Runtime [0-9:.-]+ ---//; | |
next if /^\s*$/; | |
if (m/^Start duply/) { | |
logger('info', "**Start 'duply @myduplyarg'**"); | |
next; | |
} | |
if (m/^(Changed|New|Deleted)Files (\d+)/) { | |
$buffer .= ", $1: $2"; | |
next; | |
} | |
# TotalDestinationSizeChange 1587367 (1.51 MB) | |
if (m/^TotalDestinationSizeChange.*\(([0-9.]+) ([MGK]B)\)/) { | |
$buffer = "DiffSize=$1$2, $buffer"; | |
next; | |
} | |
if (m/^SourceFileSize.*\(([0-9.]+) ([MGK]B)\)/) { | |
$buffer = "Size=$1$2$buffer"; | |
next; | |
} | |
if (m/^Start running command ([A-Z]+).*/) { | |
$state = $1; | |
next; | |
} | |
if (m/^No old backup sets found, nothing deleted/ && ($state eq 'PURGE')) { | |
next; | |
} | |
if (m/^Last full backup date/ && ($state eq 'PURGE' || $state eq 'VERIFY')) { | |
next; | |
} | |
if (m/Verify complete: \d+ files compared, 0 differences found/ && ($state eq 'VERIFY')) { | |
next; | |
} | |
if (m/^Finished state OK/) { | |
next; | |
} | |
if (m/^---+$/) { | |
logger('info', "[$state] $buffer"); | |
$buffer = ''; | |
next; | |
} | |
logger('info', "[$state] $_"); | |
} | |
close($proc); | |
if ($? > 0) { | |
logger('error', "$procname @myduplyarg exited with: $?"); | |
$localerrorcount++; | |
} elsif ($localerrorcount > 0) { | |
logger('error', "$procname @myduplyarg had $localerrorcount errors"); | |
} else { | |
$mail_content .= "$procname @myduplyarg successfully terminated\n"; | |
} | |
$mail_content .= "\n"; | |
$errorcount += $localerrorcount; | |
if ( $mailto ne '' ) { | |
push @mail_parts, MIME::Lite->new( | |
Type => 'TEXT', | |
Data => $mail_proc_content, | |
Filename => "$procname $profile @ARGV", | |
Disposition => 'attachment', | |
Top => 0, | |
); | |
} | |
} | |
if ($syslog) { | |
closelog; | |
} | |
sendmail(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment