2 # If we have rsnapshot, we have perl to run it
6 backup - manages multilevel rsnapshot backups
14 This script is intended to make B<rsnapshot>(1) backups to removable
15 devices, which are performed by hand and with some irregularity.
17 It reads C</etc/rsnapshot.conf> and finds out snapshot root and
18 list of backup levels.
20 It expected that removable device is automounted.
22 It checks existing backups in the C<$snapshot_root>, and if oldest snapshot
23 of level n is newer that next level was done (as determined by
24 modification date of C<$snapshot_root/$level-stamp>) next level is
27 If all backups were successful, unmounts all partitions of device where
28 C<$snapshot_root> is located.
30 If there exists B</usr/local/sbin/notify-messenger> invokes it and
31 sends messaage about backup completion status to its stdin
37 /usr/local/sbin/notify-messenger
41 Victor Wagner <vitus@wagner.pp.ru>
47 # Read rsnapshot conf, find out snapshot_root and retain.
48 open $conf, "<","/etc/rsnapshot.conf" or die "/etc/rsnapshot.conf:$!\n";
50 my $snapshot_root=undef;
53 if (/^snapshot_root\t+(.*)$/) {
57 if (/^retain\s+(\w+)\s+(\d+)/) {
61 push @{$levels[$#levels]},$level;
63 push @levels,[$level,$number];
66 # last level is incomplete, we don't need it.
69 die "No backup media mounted on $snapshot_root\n" unless -d $snapshot_root;
70 # Now we have following triples:
71 # "level,number,nextlevel"
75 $triple = pop @levels;
77 my $number=$triple->[1] -1;
78 my $nextlevel=$triple->[2];
79 if (! -d "$snapshot_root/$level.$number") {
80 #not enough retained backups of on this level
83 if (-f "$snapshot_root/${nextlevel}-stamp" &&
84 -M "$snapshot_root/${nextlevel}-stamp" <
85 -M "$snapshot_root/$level.$number") {
86 # last backup on level nextlevel happen after oldest retanined
90 run_rsnapshot($nextlevel);
92 open my $stamp, ">>","$snapshot_root/${nextlevel}-stamp";
95 run_rsnapshot($level);
96 notify("Backup completed successfully\n");
97 # Размонтируем файловую систему, содержащую snapshot_root
98 my @lines = `df $snapshot_root`;
99 my @line = split(/\s+/,pop @lines);
100 my $device = shift @line;
101 $device =~ s/\d$//; # remove partition number
102 open my $mount,"mount|" or die "Cannot execute mount:$!";
105 if (m!^($device\d) on !) {
111 for $device (@to_umount) {
112 print STDERR "umount $device\n";
113 if (system("umount",$device) !=0) {
114 push @baddevs, $device;
119 notify("Cannot unmount device(s) ".join(", ",@baddevs).".\n")
123 print STDERR "running rsnapshot $level\n";
124 my $status= system("rsnapshot",$level) >> 8;
126 notify("rsapshot $level finished with code $status\n");
133 my $notifier = "/usr/local/sbin/notify-messenger";
135 $hostname = Sys::Hostname::hostname();
136 open my $pipe,"|$notifier";
137 print $pipe "$hostname: $msg";