/[psinib]/psinib.pl
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /psinib.pl

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1.1.1 by dpavlin, Sat Jan 4 11:42:56 2003 UTC revision 1.12 by dpavlin, Sun Oct 12 16:13:38 2003 UTC
# Line 12  Line 12 
12  #  #
13  #  #
14  # usage:  # usage:
15  #       $ backup.pl mountscript  #       $ psinib.pl mountscript
16    
17  use strict 'vars';  use strict 'vars';
18  use Data::Dumper;  use Data::Dumper;
# Line 21  use POSIX qw(strftime); Line 21  use POSIX qw(strftime);
21  use List::Compare;  use List::Compare;
22  use Filesys::SmbClient;  use Filesys::SmbClient;
23  #use Taint;  #use Taint;
24    use Fcntl qw(LOCK_EX LOCK_NB);
25    use Digest::MD5;
26    use File::Basename;
27    
28  # configuration  # configuration
29  my $LOG_TIME_FMT = '%Y-%m-%d %H:%M:%S'; # strftime format for logfile  my $LOG_TIME_FMT = '%Y-%m-%d %H:%M:%S'; # strftime format for logfile
30  my $DIR_TIME_FMT = '%Y%m%d';            # strftime format for backup dir  my $DIR_TIME_FMT = '%Y%m%d';            # strftime format for backup dir
31    
32  my $LOG = '/var/log/backup.log';        # add path here...  my $LOG = '/var/log/backup.log';        # add path here...
33  $LOG = '/tmp/backup.log';  #$LOG = '/tmp/backup.log';
34    
35  # store backups in which directory  # store backups in which directory
36  my $BACKUP_DEST = '/data/isis_backup';  #my $BACKUP_DEST = '/backup/isis_backup';
37    my $BACKUP_DEST = '/tmp/backup/';
38    
39  # files to ignore in backup  # files to ignore in backup
40  my @ignore = ('.md5sum', '.backupignore', 'backupignore.txt');  my @ignore = ('.md5sum', '.backupignore', 'backupignore.txt');
41    
42  # open log  # open log
43  open(L, "> $LOG") || die "can't open log $LOG: $!";  open(L, ">> $LOG") || die "can't open log $LOG: $!";
44  select((select(L), $|=1)[0]);   # flush output  select((select(L), $|=1)[0]);   # flush output
45    
46    # make a lock on logfile
47    
48    my $c = 0;
49    {
50            flock L, LOCK_EX | LOCK_NB and last;
51            sleep 1;
52            redo if ++$c < 10;
53            # no response for 10 sec, bail out
54            xlog("ABORT","can't take lock on $LOG -- another $0 running?");
55            exit 1;
56    }
57    
58  # taint path: nmblookup should be there!  # taint path: nmblookup should be there!
59  $ENV{'PATH'} = "/usr/bin:/bin";  $ENV{'PATH'} = "/usr/bin:/bin";
60    
# Line 49  my $mounts = shift @ARGV || Line 65  my $mounts = shift @ARGV ||
65    
66  my @in_backup;  # shares which are backeduped this run  my @in_backup;  # shares which are backeduped this run
67    
68  my $p = new Net::Ping->new();  my $p = new Net::Ping->new("tcp", 2);
69    # ping will try tcp connect to netbios-ssn (139)
70    $p->{port_num} = getservbyname("netbios-ssn", "tcp");
71    
72  my $backup_ok = 0;  my $backup_ok = 0;
73    
74  my $smb;  my $smb;
75  my %smb_atime;  my %smb_atime;
76  my %smb_mtime;  my %smb_mtime;
77    my %file_md5;
78    
79  open(M, $mounts) || die "can't open $mounts: $!";  open(M, $mounts) || die "can't open $mounts: $!";
80  while(<M>) {  while(<M>) {
# Line 63  while(<M>) { Line 82  while(<M>) {
82          next if !/^\s*smbmount\s/;          next if !/^\s*smbmount\s/;
83          my (undef,$share,undef,$opt) = split(/\s+/,$_,4);          my (undef,$share,undef,$opt) = split(/\s+/,$_,4);
84    
85          my ($user,$passwd,$workgroup);          my ($user,$passwd,$workgroup,$ip);
86    
87          foreach (split(/,/,$opt)) {          foreach (split(/,/,$opt)) {
88                  my ($n,$v) = split(/=/,$_,2);                  my ($n,$v) = split(/=/,$_,2);
# Line 79  while(<M>) { Line 98  while(<M>) {
98                          }                          }
99                  } elsif ($n =~ m#workgroup#i) {                  } elsif ($n =~ m#workgroup#i) {
100                          $workgroup = $v;                          $workgroup = $v;
101                    } elsif ($n =~ m#ip#i) {
102                            $ip = $v;
103                  }                  }
104          }          }
105    
106          push @in_backup,$share;          push @in_backup,$share;
107    
108    
109            my ($host,$dir,$date_dir) = share2host_dir($share);
110            my $bl = "$BACKUP_DEST/$host/$dir/latest";      # latest backup
111            my $bc = "$BACKUP_DEST/$host/$dir/$date_dir";   # current one
112            my $real_bl;
113            if (-l $bl) {
114                    $real_bl=readlink($bl) || die "can't read link $bl: $!";
115                    $real_bl="$BACKUP_DEST/$host/$dir/$real_bl" if (substr($real_bl,0,1) ne "/");
116                    if (-l $bc && $real_bl eq $bc) {
117                            print "$share allready backuped...\n";
118                            $backup_ok++;
119                            next;
120                    }
121    
122            }
123    
124    
125          print "working on $share\n";          print "working on $share\n";
126    
127          my $ip = get_ip($share);          # try to nmblookup IP
128            $ip = get_ip($share) if (! $ip);
129    
130          if ($ip) {          if ($ip) {
131                  xlog($share,"IP is $ip");                  xlog($share,"IP is $ip");
132                  if ($p->ping($ip)) {                  if ($p->ping($ip)) {
133                          snap_share($share,$user,$passwd,$workgroup);                          if (snap_share($share,$user,$passwd,$workgroup)) {
134                          $backup_ok++;                                  $backup_ok++;
135                            }
136                  }                  }
137          }          }
138  }  }
# Line 104  xlog("","$backup_ok backups completed of Line 144  xlog("","$backup_ok backups completed of
144    
145  #-------------------------------------------------------------------------  #-------------------------------------------------------------------------
146    
147    
148  # get IP number from share  # get IP number from share
149  sub get_ip {  sub get_ip {
150          my $share = shift;          my $share = shift;
# Line 116  sub get_ip { Line 157  sub get_ip {
157          }          }
158  }  }
159    
160    
161    # write entry to screen and log
162  sub xlog {  sub xlog {
163          my $share = shift;          my $share = shift;
164          my $t = strftime $LOG_TIME_FMT, localtime;          my $t = strftime $LOG_TIME_FMT, localtime;
# Line 124  sub xlog { Line 167  sub xlog {
167          print L "$t $share\t$m\n";          print L "$t $share\t$m\n";
168  }  }
169    
170  sub snap_share {  # dump warn and dies into log
171    BEGIN { $SIG{'__WARN__'} = sub { xlog('WARN',$_[0]) ; warn $_[0] } }
172    BEGIN { $SIG{'__DIE__'} = sub { xlog('DIE',$_[0]) ; die $_[0] } }
173    
         my $share = shift;  
   
         my %param = ( debug => 0 );  
   
         $param{username} = shift;  
         $param{password} = shift;  
         $param{workgroup} = shift;  
174    
175    # split share name to host, dir and currnet date dir
176    sub share2host_dir {
177            my $share = shift;
178          my ($host,$dir);          my ($host,$dir);
179          if ($share =~ m#//([^/]+)/(.+)$#) {          if ($share =~ m#//([^/]+)/(.+)$#) {
180                  ($host,$dir) = ($1,$2);                  ($host,$dir) = ($1,$2);
# Line 144  sub snap_share { Line 185  sub snap_share {
185                  print "Can't parse share $share into host and directory!\n";                  print "Can't parse share $share into host and directory!\n";
186                  return;                  return;
187          }          }
188            return ($host,$dir,strftime $DIR_TIME_FMT, localtime);
189    }
190    
191    
192          my $date_dir = strftime $DIR_TIME_FMT, localtime;  # make a snapshot of a share
193    sub snap_share {
194    
195            my $share = shift;
196    
197            my %param = ( debug => 0 );
198    
199            $param{username} = shift || warn "can't find username for share $share";
200            $param{password} = shift || warn "can't find passwod for share $share";
201            $param{workgroup} = shift || warn "can't find workgroup for share $share";
202    
203            my ($host,$dir,$date_dir) = share2host_dir($share);
204    
205          # latest backup directory          # latest backup directory
206          my $bl = "$BACKUP_DEST/$host/$dir/latest";          my $bl = "$BACKUP_DEST/$host/$dir/latest";
# Line 153  sub snap_share { Line 208  sub snap_share {
208          my $bc = "$BACKUP_DEST/$host/$dir/$date_dir";          my $bc = "$BACKUP_DEST/$host/$dir/$date_dir";
209    
210          my $real_bl;          my $real_bl;
211          if (-e $bl) {          if (-l $bl) {
212                  $real_bl=readlink($bl) || die "can't read link $bl: $!";                  $real_bl=readlink($bl) || die "can't read link $bl: $!";
213                  $real_bl="$BACKUP_DEST/$host/$dir/$real_bl" if (substr($real_bl,0,1) ne "/");                  $real_bl="$BACKUP_DEST/$host/$dir/$real_bl" if (substr($real_bl,0,1) ne "/");
214          } else {          } else {
215                  print "no old backup, this is first run...\n";                  print "no old backup, trying to find last backup, ";
216                    if (opendir(BL_DIR, "$BACKUP_DEST/$host/$dir")) {
217                            my @bl_dirs = sort grep { !/^\./ && -d "$BACKUP_DEST/$host/$dir/$_" } readdir(BL_DIR);
218                            closedir(BL_DIR);
219                            $real_bl=pop @bl_dirs;
220                            print "using $real_bl as latest...\n";
221                            $real_bl="$BACKUP_DEST/$host/$dir/$real_bl" if (substr($real_bl,0,1) ne "/");
222                            if ($real_bl eq $bc) {
223                                    xlog($share,"latest from today (possible partial backup)");
224                                    rename $real_bl,$real_bl.".partial" || warn "can't reaname partial backup: $!";
225                                    $real_bl .= ".partial";
226                            }
227                    } else {
228                            print "this is first run...\n";
229                    }
230          }          }
231    
232          if (-e $bc && $real_bl && $real_bl eq $bc) {          if (-l $bc && $real_bl && $real_bl eq $bc) {
233                  print "$share allready backuped...\n";                  print "$share allready backuped...\n";
234                  return;                  return 1;
235          }          }
236    
237          die "You should really create BACKUP_DEST [$BACKUP_DEST] by hand! " if (!-e $BACKUP_DEST);          die "You should really create BACKUP_DEST [$BACKUP_DEST] by hand! " if (!-e $BACKUP_DEST);
# Line 189  sub snap_share { Line 258  sub snap_share {
258          my %file_size;          my %file_size;
259          my %file_atime;          my %file_atime;
260          my %file_mtime;          my %file_mtime;
261          my %file_md5;          #my %file_md5;
262    
263          my @smb_files;          my @smb_files;
264          my %smb_size;          my %smb_size;
265          #my %smb_atime;          #my %smb_atime;
266          #my %smb_mtime;          #my %smb_mtime;
         my %smb_md5;  
   
267    
268          sub norm_dir {          sub norm_dir {
269                  my $foo = shift;                  my $foo = shift;
# Line 212  sub snap_share { Line 279  sub snap_share {
279          my $di = 0;          my $di = 0;
280          while ($di <= $#dirs && $real_bl) {          while ($di <= $#dirs && $real_bl) {
281                  my $d=$dirs[$di++];                  my $d=$dirs[$di++];
282                  opendir(DIR,"$bl/$d") || warn "opendir($bl/$d): $!\n";                  opendir(DIR,"$real_bl/$d") || warn "opendir($real_bl/$d): $!\n";
283    
284                  # read .backupignore if exists                  # read .backupignore if exists
285                  if (-f "$bl/$d/.backupignore") {                  if (-f "$real_bl/$d/.backupignore") {
286                          open(I,"$bl/$d/.backupignore");                          open(I,"$real_bl/$d/.backupignore");
287                          while(<I>) {                          while(<I>) {
288                                  chomp;                                  chomp;
289                                  push @ignore,norm_dir("$d/$_");                                  push @ignore,norm_dir("$d/$_");
290                          }                          }
291                          close(I);                          close(I);
292  print STDERR "ignore: ",join("|",@ignore),"\n";  #print STDERR "ignore: ",join("|",@ignore),"\n";
293                          link "$bl/$d/.backupignore","$bc/$d/.backupignore" ||                          link "$real_bl/$d/.backupignore","$bc/$d/.backupignore" ||
294                                  warn "can't copy $bl/$d/.backupignore to current backup dir: $!\n";                                  warn "can't copy $real_bl/$d/.backupignore to current backup dir: $!\n";
295                  }                  }
296    
297                  # read .md5sum if exists                  # read .md5sum if exists
298                  if (-f "$bl/$d/.md5sum") {                  if (-f "$real_bl/$d/.md5sum") {
299                          open(I,"$bl/$d/.md5sum");                          open(I,"$real_bl/$d/.md5sum");
300                          while(<I>) {                          while(<I>) {
301                                  chomp;                                  chomp;
302                                  my ($md5,$f) = split(/\s+/,$_,2);                                  my ($md5,$f) = split(/\s+/,$_,2);
# Line 243  print STDERR "ignore: ",join("|",@ignore Line 310  print STDERR "ignore: ",join("|",@ignore
310                          next if ($f eq '.');                          next if ($f eq '.');
311                          next if ($f eq '..');                          next if ($f eq '..');
312                          my $pr = norm_dir("$d/$f");     # path relative                          my $pr = norm_dir("$d/$f");     # path relative
313                          my $pf = norm_dir("$d/$f","$bl/");      # path full                          my $pf = norm_dir("$d/$f","$real_bl/"); # path full
314                          if (grep(/^\Q$pr\E$/,@ignore) == 0) {                          if (grep(/^\Q$pr\E$/,@ignore) == 0) {
315                                  if (-f $pf) {                                  if (-f $pf) {
316                                          push @files,$pr;                                          push @files,$pr;
# Line 253  print STDERR "ignore: ",join("|",@ignore Line 320  print STDERR "ignore: ",join("|",@ignore
320                                  } elsif (-d $pf) {                                  } elsif (-d $pf) {
321                                          push @dirs,$pr;                                          push @dirs,$pr;
322                                  } else {                                  } else {
323                                          print STDERR "unknown type: $pf\n";                                          print STDERR "not file or directory: $pf\n";
324                                  }                                  }
325                          } else {                          } else {
326                                  print STDERR "ignored: $pr\n";                                  print STDERR "ignored: $pr\n";
# Line 261  print STDERR "ignore: ",join("|",@ignore Line 328  print STDERR "ignore: ",join("|",@ignore
328                  }                  }
329          }          }
330    
331          xlog($share,($#files+1)." files and ".($#dirs+1)." dirs on local disk before backup");          # local dir always include /
332            xlog($share,($#files+1)." files and ".($#dirs)." dirs on local disk before backup");
333    
334          # read smb filesystem          # read smb filesystem
335    
# Line 272  print STDERR "ignore: ",join("|",@ignore Line 340  print STDERR "ignore: ",join("|",@ignore
340    
341          $di = 0;          $di = 0;
342          while ($di <= $#smb_dirs) {          while ($di <= $#smb_dirs) {
343                  my $d=$smb_dirs[$di++];                  my $d=$smb_dirs[$di];
344                  my $pf = norm_dir($d,"smb:$share/");    # path full                  my $pf = norm_dir($d,"smb:$share/");    # path full
345                  my $D = $smb->opendir($pf) || warn "smb->opendir($pf): $!\n";                  my $D = $smb->opendir($pf);
346                    if (! $D) {
347                            xlog($share,"FATAL: $share [$pf]: $!");
348                            # remove failing dir
349                            delete $smb_dirs[$di];
350                            return 0;                       # failed
351                    }
352                    $di++;
353    
354                  my @clutter = $smb->readdir_struct($D);                  my @clutter = $smb->readdir_struct($D);
355                  foreach my $item (@clutter) {                  foreach my $item (@clutter) {
# Line 292  print STDERR "ignore: ",join("|",@ignore Line 367  print STDERR "ignore: ",join("|",@ignore
367                                  } elsif ($item->[0] == main::SMBC_DIR) {                                  } elsif ($item->[0] == main::SMBC_DIR) {
368                                          push @smb_dirs,$pr;                                          push @smb_dirs,$pr;
369                                  } else {                                  } else {
370                                          print STDERR "unknown type: $pf\n";                                          print STDERR "not file or directory [",$item->[0],"]: $pf\n";
371                                  }                                  }
372                          } else {                          } else {
373                                  print STDERR "smb ignored: $pr\n";                                  print STDERR "smb ignored: $pr\n";
# Line 300  print STDERR "ignore: ",join("|",@ignore Line 375  print STDERR "ignore: ",join("|",@ignore
375                  }                  }
376          }          }
377    
378          xlog($share,($#smb_files+1)." files and ".($#smb_dirs+1)." dirs on remote share");          xlog($share,($#smb_files+1)." files and ".($#smb_dirs)." dirs on remote share");
379    
380          # sync dirs          # sync dirs
381          my $lc = List::Compare->new(\@dirs, \@smb_dirs);          my $lc = List::Compare->new(\@dirs, \@smb_dirs);
# Line 332  print STDERR "ignore: ",join("|",@ignore Line 407  print STDERR "ignore: ",join("|",@ignore
407                                    
408                  foreach my $f (@_) {                  foreach my $f (@_) {
409  #print "smb_copy $from/$f -> $to/$f\n";  #print "smb_copy $from/$f -> $to/$f\n";
410                          if (! open(F,"> $to/$f")) {                          my $md5 = Digest::MD5->new;
                                 print STDERR "can't open new file $to/$f: $!\n";  
                                 next;  
                         }  
411    
412                          my $fd = $smb->open("$from/$f");                          my $fd = $smb->open("$from/$f");
413                          if (! $fd) {                          if (! $fd) {
414                                  print STDERR "can't open smb file $from/$f: $!\n";                                  xlog("WARNING","can't open smb file $from/$f: $!");
415                                    next;
416                            }
417    
418                            if (! open(F,"> $to/$f")) {
419                                    xlog("WARNING","can't open new file $to/$f: $!");
420                                  next;                                  next;
421                          }                          }
422    
423                          while (defined(my $b=$smb->read($fd,4096))) {                          while (defined(my $b=$smb->read($fd,4096))) {
424                                  print F $b;                                  print F $b;
425                                  $l += length($b);                                  $l += length($b);
426                                    $md5->add($b);
427                          }                          }
428    
429                          $smb->close($fd);                          $smb->close($fd);
430                          close(F);                          close(F);
431    
432                            $file_md5{$f} = $md5->hexdigest;
433    
434                          # FIX: this fails with -T                          # FIX: this fails with -T
435                          my ($a,$m) = ($smb->stat("$from/$f"))[10,11];                          my ($a,$m) = ($smb->stat("$from/$f"))[10,11];
436                          utime $a, $m, "$to/$f" ||                          utime $a, $m, "$to/$f" ||
# Line 404  print STDERR "ignore: ",join("|",@ignore Line 484  print STDERR "ignore: ",join("|",@ignore
484          xlog($share,"$transfer bytes transfered...");          xlog($share,"$transfer bytes transfered...");
485    
486          foreach (@ln_files) {          foreach (@ln_files) {
487                  link "$bl/$_","$bc/$_" || warn "link $bl/$_ -> $bc/$_: $!\n";                  link "$real_bl/$_","$bc/$_" || warn "link $real_bl/$_ -> $bc/$_: $!\n";
488          }          }
489    
490          # remove files          # remove files
# Line 417  print STDERR "ignore: ",join("|",@ignore Line 497  print STDERR "ignore: ",join("|",@ignore
497                  rmdir "$bc/$_" || warn "rmdir $_: $!\n";                  rmdir "$bc/$_" || warn "rmdir $_: $!\n";
498          }          }
499    
500            # remove old .md5sum
501          # FIX: create .md5sum          foreach (sort @dirs) {
502                    unlink "$bc/$_/.md5sum" if (-e "$bc/$_/.md5sum");
503            }
504    
505            # create .md5sum
506            my $last_dir = '';
507            my $md5;
508            foreach my $f (sort { $file_md5{$a} cmp $file_md5{$b} } keys %file_md5) {
509                    my $dir = dirname($f);
510                    my $file = basename($f);
511    #print "$f -- $dir / $file<--\n";
512                    if ($dir ne $last_dir) {
513                            close($md5) if ($md5);
514                            open($md5, ">> $bc/$dir/.md5sum") || warn "can't create $bc/$dir/.md5sum: $!";
515                            $last_dir = $dir;
516    #print STDERR "writing $last_dir/.md5sum\n";
517                    }
518                    print $md5 $file_md5{$f},"  $file\n";
519            }
520            close($md5) if ($md5);
521    
522          # create leatest link          # create leatest link
523    #print "ln -s $bc $real_bl\n";
524            if (-l $bl) {
525                    unlink $bl || warn "can't remove old latest symlink $bl: $!\n";
526            }
527          symlink $bc,$bl || warn "can't create latest symlink $bl -> $bc: $!\n";          symlink $bc,$bl || warn "can't create latest symlink $bl -> $bc: $!\n";
528    
529            # FIX: sanity check -- remove for speedup
530            xlog($share,"failed to create latest symlink $bl -> $bc...") if (readlink($bl) ne $bc || ! -l $bl);
531    
532          xlog($share,"backup completed...");          xlog($share,"backup completed...");
 }  
533    
534            return 1;
535    }
536    __END__
537  #-------------------------------------------------------------------------  #-------------------------------------------------------------------------
538    
539    
540    =head1 NAME
541    
542    psinib - Perl Snapshot Is Not Incremental Backup
543    
544    =head1 SYNOPSIS
545    
546    ./psinib.pl
547    
548    =head1 DESCRIPTION
549    
550    This script in current version support just backup of Samba (or Micro$oft
551    Winblowz) shares to central disk space. Central disk space is organized in
552    multiple directories named after:
553    
554    =over 4
555    
556    =item *
557    server which is sharing files to be backed up
558    
559    =item *
560    name of share on server
561    
562    =item *
563    dated directory named like standard ISO date format (YYYYMMDD).
564    
565    =back
566    
567    In each dated directory you will find I<snapshot> of all files on
568    exported share on that particular date.
569    
570    You can also use symlink I<latest> which will lead you to
571    last completed backup. After that you can use some other backup
572    software to transfer I<snapshot> to tape, CD-ROM or some other media.
573    
574    =head2 Design considerations
575    
576    Since taking of share snapshot every day requires a lot of disk space and
577    network bandwidth, B<psinib> uses several techniques to keep disk usage and
578    network traffic at acceptable level:
579    
580    =over 3
581    
582    =item - usage of hard-links to provide same files in each snapshot (as opposed
583    to have multiple copies of same file)
584    
585    =item - usage of file size, atime and mtime to find changes of files without
586    transferring whole file over network (just share browsing is transfered
587    over network)
588    
589    =item - usage of C<.md5sum> files (compatible with command-line utility
590    C<md5sum>) to keep file between snapshots hard-linked
591    
592    =back
593    
594    =head1 CONFIGURATION
595    
596    This section is not yet written.
597    
598    =head1 HACKS, TRICKS, BUGS and LIMITATIONS
599    
600    This chapter will have all content that doesn't fit anywhere else.
601    
602    =head2 Can snapshots be more frequent than daily?
603    
604    There is not real reason why you can't take snapshot more often than
605    once a day. Actually, if you are using B<psinib> to backup Windows
606    workstations you already know that they tend to come-and-go during the day
607    (reboots probably ;-), so running B<psinib> several times a day increases
608    your chance of having up-to-date backup (B<psinib> will not make multiple
609    snapshots for same day, nor will it update snapshot for current day if
610    it already exists).
611    
612    However, changing B<psinib> to produce snapshots which are, for example, hourly
613    is a simple change of C<$DIR_TIME_FMT> which is currently set to
614    C<'%Y%m%d'> (see I<strftime> documentation for explanation of that
615    format). If you change that to C<'%Y%m%d-%H> you can have hourly snapshots
616    (if your network is fast enough, that is...). Also, some of messages in
617    program will sound strange, but other than that it should work.
618    I<You have been warned>.
619    
620    =head2 Do I really need to share every directory which I want to snapshot?
621    
622    Actually, no. Due to usage of C<Filesys::SmbClient> module, you can also
623    specify sub-directory inside your share that you want to backup. This feature
624    is most useful if you want to use administrative shares (but, have in mind
625    that you have to enter your Win administrator password in unencrypted file on
626    disk to do that) like this:
627    
628            smbmount //server/c$/WinNT/fonts  /mnt  -o username=administrator%win  
629    
630    After that you will get directories with snapshots like:
631    
632            server/c_WinNT_fonts/yyyymmdd/....
633    
634    =head2 Won't I run out of disk space?
635    
636    Of course you will... Snapshots and logfiles will eventually fill-up your disk.
637    However, you can do two things to stop that:
638    
639    =head3 Clean snapshort older than x days
640    
641    You can add following command to your C<root> crontab:
642    
643            find /backup/isis_backup -type d -mindepth 3 -maxdepth 3 -mtime +11 -exec rm -Rf {} \;
644    
645    I assume that C</backup/isis_backup> is directory in which are your snapshots
646    and that you don't want to keep snapshots older than 11 days (that's
647    C<-mtime +11> part of command).
648    
649    =head3 Rotate your logs
650    
651    I will leave that to you. I relay on GNU/Debian's C<logrotate> to do it for me.
652    
653    =head2 What are I<YYYYMMDD.partial> directories?
654    
655    If there isn't I<latest> symlink in snapshot directory, it's preatty safe to
656    assume that previous backup from that day failed. So, that directory will
657    be renamed to I<YYYYMMDD.partial> and snapshot will be performed again,
658    linking same files (other alternative would be to erase that dir and find
659    second-oldest directory, but this seemed like more correct approach).
660    
661    =head1 AUTHOR
662    
663    Dobrica Pavlinusic <dpavlin@rot13.org>
664    
665    L<http://www.rot13.org/~dpavlin/>
666    
667    =head1 LICENSE
668    
669    This product is licensed under GNU Public License (GPL) v2 or later.
670    
671    =cut

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.12

  ViewVC Help
Powered by ViewVC 1.1.26