作者:xuejiang
问题描述:
   用svnadmin hotcopy备份的svn库是svn一个完整拷贝,保证了备份的完整、可靠。但用这种方式备份出现的问题是:备份占用空间比较大,需要定期进行删除,而我们发现删除非常困难。
  尝试如下:
1、输入:rm -rf repos_backup1
   提示访问拒绝。进到 repos/db/revs里面发现里面的文件权限都是
  -r--r--r--
这样的,所以谁也不能用上面的命令进行删除了。
2、输入:rm -R repos_backup1
  遇到每个文件都提示:是否重写权限,选择是,才会删除成功:
override rwxrwx---  4294967294/users for 1117/repos1/db/revprops/11249?  
一个库往往有数十个万个文件,这种删除方式显然不现实。

3、输入:chmod -R 777 repos_backup1;rm -R repos_backup1
   等待半天,提示堆栈溢出。输入ulimit -a查看,堆栈限制为7715;修改这个参数必须重启系统,服务器级别比较高,不敢重启,只好作罢。

  于是想到了用脚本来进行删除。

删除备份方案设计如下:
目标:定期删除备份数据,并保证备份数据一直介于7到16份之间
步骤:1、每月1号删除上个月21号之前所有数据
      2、每月15号删除上个月所有数据和本月8号前的所有数据
      3、每月25号删除本月19号之前的所有数据。
用perl脚本实现,代码如下:

#! /usr/bin/perl 
# Author:xuejiang 
# Site: http://www.scmbbs.com 

#本单元:定期删除备份数据,并保证备份数据一直介于7到16份之间, 
#适用:备份目录以mmdd的日期格式命名。 

use Cwd; 
use File::Find; 

&main(); 

sub main() 
{ 
#取得当前时间,根据时间设置定期进行删除 
my $targetDir="/home/backup/svn/hotcopy2/"; #定义备份目录。 
my( $sec, $min, $hour, $day, $month, $year,$wday,$yday ) = localtime( time() ); 
$month++; 
my $today = sprintf( "%02d", $day); 
if ($today !~ /(01$|15$|25$|)/) 
{ 
    exit(0); 
} 
my $monthday= sprintf( "%02d%02d", $month, $day); 
my $thismonth= sprintf("%02d",$month); 
my ($lastmonth,$passdate,$tempstr); 
#定义删除的目录数组,对每个目录调用函数deleteDir进行删除。 
chdir($targetDir); 
my @dir=<*>; 
print @dir; 
if($thismonth=~/01/) 
{ 
                $lastmonth='12'; 
}else 
{ 
                $lastmonth=$thismonth - 1; 
} 
foreach my $dir(@dir) 
{ 
      if ($dir =~ /[^0-9]/) 
      { 
          next; 
      } 
#每月1号删除上个月21号之前所有数据 
        if ($today=~/01$/) 
        { 
            $passdate=$lastmonth.'21';     
            if ($lastmonth == '12') 
            { 
                $tempstr= substr($dir,0,2); 
                if (($tempstr ne "01")&&($dir < $passdate)) 
                { 
                    &deleteDir($targetDir.$dir); 
                } 
            }else 
            { 
                if ($dir < $passdate) 
                { 
                    &deleteDir($targetDir.$dir); 
                } 
            } 
        } 
#每月15号删除上个月所有数据和本月8号前的所有数据 
   if ($today=~ /15$/) 
   { 
           $passdate=$thismonth.'08'; 
           if ($dir < $passdate) 
            { 
                    &deleteDir($targetDir.$dir); 
            } 
            if ($lastmonth == '12') 
            { 
                $tempstr= substr($dir,0,2); 
                if ($tempstr == "12") 
                { 
                    &deleteDir($targetDir.$dir); 
                } 
            } 
   } 
#每月25号删除本月19号之前的所有数据。 
   if ($today=~ /25$/) 
   { 
           $passdate=$thismonth.'19'; 
           if ($dir < $passdate) 
            { 
                    &deleteDir($targetDir.$dir); 
            } 
            if ($lastmonth == '12') 
            { 
                $tempstr= substr($dir,0,2); 
                if ($tempstr == "12") 
                { 
                    &deleteDir($targetDir.$dir); 
                } 
            } 
   } 
} 
} 
#递归遍历各目录,遍历各个文件,每个文件先进行chmod 777 filename操作,再进行 rm -rf filename操作。 

sub deleteDir($) 
{ 
        my ($dir)=@_; 
        print "log in the dir:$dir /n"; 
        my $handle; 
        opendir($handle,$dir); 
        while(defined(my $ndir=readdir($handle))) 
        { 
                  if (($ndir eq ".")||($ndir eq "..")) 
                  { 
                        next; 
                  } 
                $ndir=$dir."/".$ndir; 
                if (-f $ndir) 
                { 
                        ls `chmod 777 $ndir`; ##如果需要此步。 
                        print "file:$ndir/n" if unlink($ndir); 
                }else 
                { 
                        print "Dir:$ndir/n"; 
                        deleteDir($ndir); 
                } 
        } 
        closedir($handle); 
        rmdir($dir); 
        print "now locate:$dir/n"; 
}