3 # Check the status of da-backup backups
4 # Copyright 2007 Stephen Gran <sgran@debian.org>
5 # Copyright 2008 Peter Palfrader
7 # Permission is hereby granted, free of charge, to any person obtaining
8 # a copy of this software and associated documentation files (the
9 # "Software"), to deal in the Software without restriction, including
10 # without limitation the rights to use, copy, modify, merge, publish,
11 # distribute, sublicense, and/or sell copies of the Software, and to
12 # permit persons to whom the Software is furnished to do so, subject to
13 # the following conditions:
15 # The above copyright notice and this permission notice shall be
16 # included in all copies or substantial portions of the Software.
18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 my $DABACKUP_CONF = '/etc/da-backup.conf';
33 my $MAX_AGE = 40*60*60;
35 my $MAX_LOCK_AGE = 24*60*60;
36 my $LOCKFILE = '/var/lock/da-backup.lock';
45 $SIG{__DIE__ } = sub() {
47 exit $CODE{'UNKNOWN'};
51 my $EXITCODE = 'UNDEF';
55 my ($code, $msg, $resource) = @_;
56 $MESSAGE{$msg} = [] unless defined $MESSAGE{$msg};
57 push @{$MESSAGE{$msg}}, $resource;
58 $EXITCODE = ($CODE{$code} > $CODE{$EXITCODE}) ? $code : $EXITCODE;
63 my ($exitcode, $fd) = @_;
65 print $fd "Usage: $PROGRAM_NAME --help\n";
66 print $fd "Usage: $PROGRAM_NAME [--fresh <minseconds>] [--maxage <seconds>]";
72 Getopt::Long::config('bundling');
74 'h|help' => \$params->{'help'},
75 'f|fresh=i' => \$TOO_FRESH,
76 'm|maxage=i' => \$MAX_AGE,
77 'M|maxlockage=i' => \$MAX_LOCK_AGE,
79 die ("$PROGRAM_NAME: Usage: $PROGRAM_NAME [-fwhv]\n");
82 help(0, *STDOUT) if $params->{'help'};
83 help(1, *STDERR) if scalar @ARGV > 0;
86 unless (-e $DABACKUP_CONF) {
87 if (-e '/etc/da-backup') {
88 print "WARNING: No $DABACKUP_CONF, but we have /etc/da-backup/\n";
89 exit $CODE{'WARNING'};
91 if (-e '/var/log/da-backup') {
92 print "WARNING: No $DABACKUP_CONF, but we have /var/log/da-backup/\n";
93 exit $CODE{'WARNING'};
95 print "OK: da-backup not installed\n";
102 open (FH, "< $DABACKUP_CONF") or die ("Cannot open $DABACKUP_CONF: $!\n");
104 if (/confdir=(.*)/) {
106 } elsif (/logdir=(.*)/) {
111 die ("No confdir found in $DABACKUP_CONF") unless defined $confdir;
112 die ("No logdir found in $DABACKUP_CONF") unless defined $logdir;
114 opendir(DIR, $confdir) or die ("Cannot opendir $confdir: $!\n");
115 my %conffiles = map {$_ => 1} grep { !/^\./ && !/\.bak$/} readdir(DIR);
118 opendir(DIR, $logdir) or die ("Cannot opendir $logdir: $!\n");
119 my %logfiles = map {$_ => 1} grep { !/^\./ && !/\.[0-9]+(\.gz)?$/} readdir(DIR);
122 if (scalar keys %conffiles == 0) {
123 print "WARNING: da-backup installed but no backups configured\n";
124 exit $CODE{'WARNING'};
127 for my $f (keys %conffiles) {
128 unless (exists $logfiles{$f}) {
129 problem('WARNING', 'no log', $f);
134 for my $f (sort {$a cmp $b} keys %logfiles) {
135 unless (exists $conffiles{$f}) {
136 problem('WARNING', 'no config', $f);
140 my @stat = stat("$logdir/$f") or die ("Cannot stat $logdir/$f: $!\n");
141 my $age = time - $stat[10];
144 if (my @lockstat = stat($LOCKFILE)) {
145 $lockage = time - $lockstat[10];
148 if ($age < $TOO_FRESH || (defined $lockage && $lockage < $MAX_LOCK_AGE)) { # File is too new, let's use the old one
149 if (-e "$logdir/$f.0") {
151 my @stat = stat("$logdir/$f") or die ("Cannot stat $logdir/$f: $!\n");
152 $age = time - $stat[10];
157 problem('WARNING', 'future timestamp', $f);
159 } elsif ($age > $MAX_AGE) {
162 if ($age > 48 * 3600) {
163 $hage = sprintf("%d days", $age / 24 / 3600);
165 $hage = sprintf("%d hours", $age / 3600);
167 problem('WARNING', 'old', "$f ($hage)");
171 open(FH, "< $logdir/$f") or die ("Cannot open $logdir/$f: $!\n");
172 sysseek(FH, -1024, SEEK_END); # just try it - doesn't matter if it fails
177 if (/^sent\s+[\d,]+\s+bytes\s+received\s+[\d,]+\s+bytes\s+[\d,\.]+\s+bytes\/sec$/) {
178 problem('OK', 'probably ok', $f);
185 problem('CRITICAL', 'FAILED', "$f ($last2 $last)");
188 my $msg = join("; ", map {"$_: ".join(', ', @{$MESSAGE{$_}}) } (sort {$a cmp $b} keys %MESSAGE));
189 print $EXITCODE, ": ", $msg, "\n";
190 exit $CODE{$EXITCODE};