Created
March 25, 2011 07:58
-
-
Save DirkR/886516 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=2 ts=2 et | |
# (C) 2011 Dirk Ruediger <dirk@niebegeg.net> | |
# Feel free do hack or adopt it! | |
# | |
# A syslog wrapper for duply. It runs duply, filers "bias" out and | |
# writes all important and unexpected messages to syslog. | |
# | |
# usage: | |
# Like duply. all arguments are passed to duply | |
# | |
# duplyreport.pl profilename backup_verify_purge | |
# | |
# etc. | |
# The script should not produce any output to console. | |
use warnings; | |
use strict; | |
use Getopt::Long; | |
use Date::Format; | |
use File::Basename; | |
use Proc::PID::File; | |
my $procname = 'duply'; | |
my $program = basename($0); | |
my $state = 'nostate'; | |
my $buffer = ''; | |
my @profiles = (); | |
my $mailto = ''; | |
my $syslog = 0; | |
my $help = 0; | |
my $mail_content = ''; | |
my $result = GetOptions ("syslog|s" => \$syslog, | |
"help|h" => \$help, | |
"profile|p=s" => \@profiles, | |
"mail|m=s" => \$mailto); | |
if ($help) { | |
print <<"USAGE"; | |
Usage: $program [-s] [-h] [-m address] -p profile [-p profile [-p profile...]] action | |
-s Log to syslog | |
-m address Mail log to address | |
-h Print this usage message | |
-p profile define a duply profile, multiple profiles are possible. | |
If no profiles are defined, then take "all profiles that do not contain a file named 'skip'". | |
action duplicity action to be performed, defaults to "backup" | |
USAGE | |
exit 0; | |
} | |
if (scalar(@ARGV) == 0) { | |
push(@ARGV, 'backup'); | |
} | |
if (scalar(@profiles) == 0) { | |
@profiles = get_all_profiles(); | |
} | |
my $timestr = time2str('%c', time); | |
if ($syslog) { | |
use Unix::Syslog qw(:subs :macros); | |
openlog "duply", LOG_PID | LOG_INFO, LOG_LOCAL0; | |
} | |
if (Proc::PID::File->running()) { | |
logger("error", "$program is already running. I'll exit here."); | |
exit(0); | |
} | |
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; | |
} | |
} | |
sub get_all_profiles { | |
my @profiles = (); | |
foreach my $config_file (glob('/etc/duply/*/conf')) { | |
my $profile_folder = dirname($config_file); | |
if (! -f "$profile_folder/skip") { | |
push @profiles, basename($profile_folder); | |
} | |
} | |
return @profiles; | |
} | |
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 .= ($level ne 'info' ? uc($level) : '') . " $message\n"; | |
} | |
if (! $syslog && $mailto eq '') { | |
print (($level ne 'info' ? uc($level) : '') . " $message\n"); | |
} | |
} | |
foreach my $profile (@profiles) { | |
my $proc; | |
unless (open($proc, "LC_ALL=C $procname $profile @ARGV 2>&1 |")) { | |
logger('error', "Could not start $procname process: $!"); | |
die "Could not start $procname process: $!"; | |
} | |
while (<$proc>) { | |
chomp; | |
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|TotalDestinationSizeChange|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/ || | |
/^Reuse configured PASSPHRASE as SIGN_PASSPHRASE/ || | |
/Import of duplicity.backends.\w+backend Failed: No module named/; | |
s/^--- //; | |
s/ at [0-9:.]+ - Runtime [0-9:.-]+ ---//; | |
next if /^\s*$/; | |
if (m/^Start duply/) { | |
logger('info', "**Start 'duply $profile @ARGV'**"); | |
next; | |
} | |
if (m/^(Changed|New|Deleted)Files (\d+)/) { | |
$buffer .= ", $1: $2"; | |
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] $_"); | |
} | |
if ($mailto ne '') { | |
$mail_content .= "\n"; | |
} | |
} | |
if ($syslog) { | |
closelog; | |
} | |
if ($mailto ne '') { | |
open (my $mail, "| mail -s 'Duply report: $timestr' $mailto"); | |
print $mail $mail_content; | |
close $mail; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment