Unfortunately there is no notification at all if this happens. No mail, no hint, no nothing.
So I had the idea to write a small perl script which is checking every hour (by cron) how old the last successful backup is, and give me a growl notification if it's older than 2 hours.
So without any further ado, this is the script. Copy and Paste it into a file called "time-machine-check.pl", make it executable and put into your crontab something like this:
7 * * * * /Users/shk/bin/time-machine-check.pl
to make it execute every 7 minutes after the hour.
#!/usr/bin/perl
use strict;
use warnings;
use Time::Local;
use File::Basename;
use Getopt::Long qw(:config no_ignore_case);
use Pod::Usage;
my $MAXAGO= 2;
my $DEFAULTS = '/usr/bin/defaults';
my $LOCK_FILE = '/private/tmp/.'.(basename $0);
my $TM_FILE = '/private/var/db/.TimeMachine.Results';
my $KEY= 'BACKUP_COMPLETED_DATE';
my @READ_BACKUP = ($DEFAULTS, 'read', $TM_FILE, $KEY);
my @GROWL_NOTIFY= ('/usr/local/bin/growlnotify',
'-t' => 'Last backup too long ago!',
'-n' => 'Time Machine',
'-a' => 'Time Machine',
'-w',
);
my (
$test,
$age,
);
help() unless GetOptions(
't' => \$test,
'a=i' => \$age,
'h|help' => \&help,
'm|man' => \&man,
);
$age||= $MAXAGO;
sub help { pod2usage(-verbose=>1); exit; }
sub man { pod2usage(-verbose=>2); exit; }
# Get date of last successful backup
my $lastbackup= execute(@READ_BACKUP);
my ($y,$m,$d,$H,$M,$S)= ($lastbackup=~ /^(\d+)-(\d+)-(\d+)\s+(\d+):(\d+):(\d+)\s/);
my $ago= time - timelocal($S, $M, $H, $d, $m-1, $y);
# Convert to hours
$ago/= 3600;
# Prepare the message
my $msg;
if ($ago >= 24) {
$msg= plural(int($ago/24), "%d day", "%d days");
}
elsif ($ago >= 1) {
$msg= plural(int($ago), "%d hour", "%d hours");
}
else {
$msg= plural(int($ago*60), "%d minute", "%d minutes");
}
# Do we already have a message and is it younger than 1 day?
my $second_message;
if (-e $LOCK_FILE) {
my $second_message= 1;
if (-M $LOCK_FILE < 1) {
undef $msg unless $test;
}
}
# Make the message sticky by default
my $sticky= '-s';
if ($ago < $age) {
# unless it's a test message and not an alert
$sticky= '';
undef $msg unless $test;
}
# Now display the message
my $lf;
if ($sticky) {
open $lf, '>>', $LOCK_FILE;
print $lf $$,$/;
close $lf;
$lf= $LOCK_FILE unless $second_message;
END {
unlink $lf if defined $lf;
}
}
execute(@GROWL_NOTIFY, $sticky, '-m' => "The last successful backup was done more than $msg ago.") if $msg;
sub plural {
my($num, $singular, $plural, $zero)= @_;
if ($num == 1) {
return sprintf($singular, $num);
}
if ($zero and not $num) {
return $zero;
}
return sprintf($plural, $num);
}
sub execute {
open my $in, '-|', @_ or die "Failed to execute\n\t".join(' ',@_).": $!\n";
$_= do { local $/; <$in> };
close $in;
return $_;
}
=head1 NAME
time-machine-check.pl - a small script to notify via growl when no backup was done.
=head1 SYNOPSIS
time-machine-check.p -a hours -t
=head1 DESCRIPTION
This is a small perl script to be used as a cronjob like so:
7 * * * * /usr/local/bin/time-machine-check.pl -a 2
which will give a growl notification in case the last backup is older than 2 hours.
=head1 OPTIONS
=over 4
=item B<-a> hours
Maximum allowed backup age before notifying.
=item B<-t>
Test option. Notify in any case.
=back
=head1 BUGS
none yet
=head1 TODO
let's see...
=author
time-machine-check-2012.mail.skeeve@xoxy.net
=cut