Recursive rsync backup script

From Admin-SIG

coreBackup.pl

#!/usr/bin/perl -w
#
# Use rsync (and a remote rsyncd) to back up the IMPORTANT stuff on a system.
#   Create a file /.backupList containing directories to be backed up.
#
#   If that directory does NOT have a .backupList file, the whole
#   folder will be backed up.  (Except for exceptions listed in
#   .backupExclude)
#
#   If it does have a .backupList file, only the files/directories
#   in that list will be backed up.
#
#   Each directory to be backed up will be checked for another .backupList file

sub rsyncCmd{
  local ($dir,$dest) = @_;

  local $cmd = "rsync -arcz --password-file=/etc/rsync.password";
  $cmd .= " \"--exclude-from=$dir/.backupExclude\"" if (-f "$dir/.backupExclude");
  $cmd .= " \"$dir\" \"$dest\"";
  return($cmd);
}

($#ARGV == 1) or die "\nUsage: $0 host::volume directory
   where host is the remote rsyncd host, and
         volume is the backup volume enabled on that host.
   directory is the local directory to rsync.

Note that the directory CONTAINING directory must exist
on the remote backup server, or the command will fail.\n\n";

#$rsyncFmt .= $ARGV[0];  # add on host::volume spec.
$dest = $ARGV[0];  # host::volume spec.

($parent, $leaf, $dir) = &splitPath($ARGV[1]);
$_ = $leaf;  # supress warning.
#print "$parent!$leaf!$dir\n";

$listFile = "$dir/.backupList";
if (!(-f $listFile))
  { # backup this folder recursively
    $cmd = &rsyncCmd($dir,$dest . $parent);
system("date");
    print "$cmd\n";
    exec($cmd);
  }

# process .backupList
@list = &loadList($listFile);

foreach $item (@list)
  {
    local $a = "$dir/$item";
    if (-f $a)
      { # just a file, back it up
        local $t = $dest;
        $t .= "/$parent" if ($parent ne "");
        #$cmd = &rsyncCmd($a,$dest . );
        $cmd = &rsyncCmd($a,$t);
        print "$cmd\n";
        system($cmd);
      }
    else
      { # backup the folder, recursive call
        $cmd = sprintf("$0 %s \"%s\"",$ARGV[0],$a);
        print "$cmd\n";
        system($cmd);
      }
  }

#---------------------------------------------------------
sub splitPath {
  local ($dir) = @_;

  $_ = $dir;
  s/^\s+//;
  s/\s+$//;

  return("","","") if ($_ eq "/");

  chomp;
  #print "dir=$dir\n";
  local @p = split(/\//,$dir);
  #foreach(@p){print "\"$_\" ";}print "\n";
  return(join("/",@p[0..$#p-1]),$p[$#p],$dir);
}

# process comments and blank lines from list
sub loadList{
  local ($fNam) = @_;

  open(F,"<$fNam") or return;
  local @list;
  while(<F>)
    {
      chomp;
      s/#.*$//;
      s/^\s+//;
      s/\s+$//;
      @list = (@list,$_) if (m/.+/);
    }
  close(F);
  return(@list);
}