#!/usr/local/bin/perl use warnings; use strict; $|++; use vars qw( $LOGDIR $TESTING $TAPEPATH $DISKPATH %DRIVES $DUMP $REMOTE $FSSNAP $SNAPPATH $SUDO ); do '/etc/ufsdump.config' or die "No/bad /etc/ufsdump.config\n"; $FSSNAP ||= "/usr/sbin/fssnap"; $DUMP ||= "/usr/sbin/ufsdump"; $SUDO ||= "/usr/local/bin/sudo"; use vars qw( @KEEP @LEVELS $DEFAULT ); @LEVELS = qw(4 4 4 4 4 4 2); # Levels of backup, by day of the week @KEEP = qw(0 0 1 0 2 0 0 0 0 0); # How many of each level (0-9) to keep $DEFAULT = { dump => $DISKPATH, schedule => \@LEVELS, keep => \@KEEP }; $SNAPPATH ||= $DISKPATH; # If you want to back up a disk to a different place, then you can reset its # entry in %DRIVES, like this: # $DRIVES{'ext04'} = { 'physical' => '/dev/rdsk/c7t4d0s0', keep => \@KEEP, # 'dump' => '/export/riga/ext8', schedule => \@LEVELS # }; my $day = 60 * 60 * 24; my $daynum = (localtime(time))[6]; my $currday = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')[$daynum]; foreach my $drive (sort keys %DRIVES) { my $info = ref $DRIVES{$drive} ? $DRIVES{$drive} : $DEFAULT; my $raw = ref $DRIVES{$drive} ? $$info{'physical'} : $DRIVES{$drive}; my $fssnap = "\`$FSSNAP -F ufs -o raw,bs=$SNAPPATH,unlink $raw\`"; my $level = $$info{schedule}[$daynum]; next unless defined $level; my $file = "$$info{dump}/$drive.$level"; my $time = sprintf("%04d-%02d-%02d", (localtime)[5] + 1900, (localtime)[4] + 1, (localtime)[3]); my $log = "$LOGDIR/$drive.$level.$time"; my $modified = (stat $file)[9]; if ( $modified && date($modified) eq date(time) ) { warn "Already backed up $drive today: ", scalar localtime($modified), "\n"; next; } else { rotate($file, $$info{keep}[$$info{schedule}[$daynum]]); my $string = join('', "$DUMP ", $level, "aNfu $log $raw $file $fssnap"); print "$string\n"; unless ($TESTING) { stop_ntp(); system("$string"); system("$FSSNAP -F ufs -d $raw"); start_ntp(); } } } sub stop_ntp { system("$SUDO /etc/init.d/xntpd stop > /dev/null 2>&1"); } sub start_ntp { system("$SUDO /etc/init.d/xntpd start > /dev/null 2>&1"); } sub rotate { my ($file, $tokeep) = @_; for (my $i = $tokeep; $i >= 0; $i--) { my $next = $i+1; next unless (-f "$file.$i"); if ($tokeep <= $i) { print " Removing $file.$i\n" ; unlink("$file.$i") unless $TESTING; } else { print " Renaming $file.$i to $file.$next\n"; rename("$file.$i", "$file.$next") unless $TESTING; } } if (-f $file) { if ($tokeep > 0) { print " Renaming $file to $file.1\n"; rename( $file, "$file.1" ) unless $TESTING; } else { print " Removing $file\n"; unlink ($file) unless $TESTING; } } } sub date { my $time = shift || time; my $day = (localtime($time))[3]; my $monthnum = (localtime($time))[4]; my $month = (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec))[$monthnum]; my $year = (localtime($time))[5] + 1900; sprintf("%02d %03s %04d", $day, $month, $year); }