]> www.wagner.pp.ru Git - oss/restore.git/blob - backup
a6d01376f60205d6e2ec9279e59c940965a68272
[oss/restore.git] / backup
1 #!/usr/bin/perl
2 # If we have rsnapshot, we have perl to run it
3
4 =head1 NAME
5
6 backup - manages multilevel rsnapshot backups
7
8 =head1 SYNOPSIS
9
10     backup
11
12 =head1 DESCRIPTION
13
14 This script is intended to make B<rsnapshot>(1) backups to removable
15 devices, which are performed by hand and with some irregularity.
16
17 It reads C</etc/rsnapshot.conf> and finds out snapshot root and
18 list of backup levels.
19
20 It expected that removable device is automounted.
21
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
25 performed.
26
27 If all backups were successful, unmounts all partitions of device where
28 C<$snapshot_root> is located.
29
30 =head1 FILES
31
32 /etc/rsnapshot.conf
33
34 =head1 AUTHOR
35
36 Victor Wagner <vitus@wagner.pp.ru>
37
38 =cut
39
40 # Read rsnapshot conf, find out snapshot_root and retain.
41 open $conf, "<","/etc/rsnapshot.conf" or die "/etc/rsnapshot.conf:$!\n";
42 my @levels=();
43 my $snapshot_root=undef;
44 LINE:
45 while (<$conf>) {
46         if (/^snapshot_root\t+(.*)$/) {
47                 $snapshot_root= $1;
48                 next LINE;
49         }       
50         if (/^retain\s+(\w+)\s+(\d+)/) {
51                 my $level = $1;
52                 my $number = $2;
53                 if (@levels) {
54                         push @{$levels[$#levels]},$level;
55                 }
56                 push @levels,[$level,$number];
57         }
58 }
59 # last level is incomplete, we don't need it.
60 pop @levels;
61
62 die "No backup media mounted on $snapshot_root\n" unless -d $snapshot_root;
63 # Now we have following triples:
64 # "level,number,nextlevel"
65 my $level;
66 LEVEL:
67 while (@levels) {
68         $triple = pop @levels;
69         $level=$triple->[0];
70         my $number=$triple->[1] -1;
71         my $nextlevel=$triple->[2];
72         if (! -d "$snapshot_root/$level.$number") {
73             #not enough retained backups of on this level
74                 next LEVEL;
75         }
76         if (-f "$snapshot_root/${nextlevel}-stamp" &&
77                 -M "$snapshot_root/${nextlevel}-stamp" < 
78                 -M "$snapshot_root/$level.$number") {
79                 # last backup on level nextlevel happen after oldest retanined
80                 # on level level
81                 next LEVEL;
82         }
83     run_rsnapshot($nextlevel);
84         # touch stamp file
85         open my $stamp, ">>","$snapshot_root/${nextlevel}-stamp";
86         close $stamp;
87 }
88 run_rsnapshot($level);  
89 # Размонтируем файловую систему, содержащую snapshot_root
90 my @lines = `df $snapshot_root`;
91 my @line = split(/\s+/,pop @lines);
92 my $device = shift @line;
93 $device =~ s/\d$//; # remove partition number 
94 open my $mount,"mount|" or die "Cannot execute mount:$!";
95 my @to_umount=();
96 while (<$mount>) {
97         if (m!^($device\d) on !) {
98                 push @to_umount,$1;
99         }
100 }
101 close $mount;
102 for $device (@to_umount) {
103     print STDERR  "umount $device\n";
104         system("umount",$device);
105 }
106
107 sub run_rsnapshot {
108     my $level = shift;
109     print STDERR "running rsnapshot $level\n";
110     my $status= system("rsnapshot",$level) >> 8;
111     if ($status) { 
112         print STDERR "rnsapshot $level finished with code $status\n";
113         exit $status;
114     }
115 }