📄 rsync.pm
字号:
#============================================================= -*-perl-*-## BackupPC::Xfer::Rsync package## DESCRIPTION## This library defines a BackupPC::Xfer::Rsync class for managing# the rsync-based transport of backup data from the client.## AUTHOR# Craig Barratt <cbarratt@users.sourceforge.net>## COPYRIGHT# Copyright (C) 2002-2007 Craig Barratt## This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA##========================================================================## Version 3.1.0, released 25 Nov 2007.## See http://backuppc.sourceforge.net.##========================================================================package BackupPC::Xfer::Rsync;use strict;use BackupPC::View;use BackupPC::Xfer::RsyncFileIO;use Encode qw/from_to encode/;use vars qw( $RsyncLibOK $RsyncLibErr );BEGIN { eval "use File::RsyncP;"; if ( $@ ) { # # Rsync module doesn't exist. # $RsyncLibOK = 0; $RsyncLibErr = "File::RsyncP module doesn't exist"; } else { # # Note: also update configure.pl when this version number is changed! # if ( $File::RsyncP::VERSION < 0.68 ) { $RsyncLibOK = 0; $RsyncLibErr = "File::RsyncP module version" . " ($File::RsyncP::VERSION) too old: need 0.68"; } else { $RsyncLibOK = 1; } }};sub new{ my($class, $bpc, $args) = @_; return if ( !$RsyncLibOK ); $args ||= {}; my $t = bless { bpc => $bpc, conf => { $bpc->Conf }, host => "", hostIP => "", shareName => "", badFiles => [], # # Various stats # byteCnt => 0, fileCnt => 0, xferErrCnt => 0, xferBadShareCnt => 0, xferBadFileCnt => 0, xferOK => 0, # # User's args # %$args, }, $class; return $t;}sub args{ my($t, $args) = @_; foreach my $arg ( keys(%$args) ) { $t->{$arg} = $args->{$arg}; }}sub useTar{ return 0;}sub start{ my($t) = @_; my $bpc = $t->{bpc}; my $conf = $t->{conf}; my(@fileList, $rsyncClientCmd, $rsyncArgs, $logMsg, $incrDate, $argList, $fioArgs); # # We add a slash to the share name we pass to rsync # ($t->{shareNameSlash} = "$t->{shareName}/") =~ s{//+$}{/}; if ( $t->{type} eq "restore" ) { $rsyncClientCmd = $conf->{RsyncClientRestoreCmd}; $rsyncArgs = $conf->{RsyncRestoreArgs}; my $remoteDir = "$t->{shareName}/$t->{pathHdrDest}"; $remoteDir =~ s{//+}{/}g; from_to($remoteDir, "utf8", $conf->{ClientCharset}) if ( $conf->{ClientCharset} ne "" ); $argList = ['--server', @$rsyncArgs, '.', $remoteDir]; $fioArgs = { client => $t->{bkupSrcHost}, share => $t->{bkupSrcShare}, viewNum => $t->{bkupSrcNum}, fileList => $t->{fileList}, }; $logMsg = "restore started below directory $t->{shareName}" . " to host $t->{host}"; } else { # # Turn $conf->{BackupFilesOnly} and $conf->{BackupFilesExclude} # into a hash of arrays of files, and $conf->{RsyncShareName} # to an array # $bpc->backupFileConfFix($conf, "RsyncShareName"); if ( defined($conf->{BackupFilesOnly}{$t->{shareName}}) ) { my(@inc, @exc, %incDone, %excDone); foreach my $file ( @{$conf->{BackupFilesOnly}{$t->{shareName}}} ) { # # If the user wants to just include /home/craig, then # we need to do create include/exclude pairs at # each level: # --include /home --exclude /* # --include /home/craig --exclude /home/* # # It's more complex if the user wants to include multiple # deep paths. For example, if they want /home/craig and # /var/log, then we need this mouthfull: # --include /home --include /var --exclude /* # --include /home/craig --exclude /home/* # --include /var/log --exclude /var/* # # To make this easier we do all the includes first and all # of the excludes at the end (hopefully they commute). # $file =~ s{/$}{}; $file = "/$file"; $file =~ s{//+}{/}g; if ( $file eq "/" ) { # # This is a special case: if the user specifies # "/" then just include it and don't exclude "/*". # push(@inc, $file) if ( !$incDone{$file} ); next; } my $f = ""; while ( $file =~ m{^/([^/]*)(.*)} ) { my $elt = $1; $file = $2; if ( $file eq "/" ) { # # preserve a tailing slash # $file = ""; $elt = "$elt/"; } push(@exc, "$f/*") if ( !$excDone{"$f/*"} ); $excDone{"$f/*"} = 1; $f = "$f/$elt"; push(@inc, $f) if ( !$incDone{$f} ); $incDone{$f} = 1; } } foreach my $file ( @inc ) { $file = encode($conf->{ClientCharset}, $file) if ( $conf->{ClientCharset} ne "" ); push(@fileList, "--include=$file"); } foreach my $file ( @exc ) { $file = encode($conf->{ClientCharset}, $file) if ( $conf->{ClientCharset} ne "" ); push(@fileList, "--exclude=$file"); } } if ( defined($conf->{BackupFilesExclude}{$t->{shareName}}) ) { foreach my $file ( @{$conf->{BackupFilesExclude}{$t->{shareName}}} ) { # # just append additional exclude lists onto the end # $file = encode($conf->{ClientCharset}, $file) if ( $conf->{ClientCharset} ne "" ); push(@fileList, "--exclude=$file"); } } if ( $t->{type} eq "full" ) { if ( $t->{partialNum} ) { $logMsg = "full backup started for directory $t->{shareName};" . " updating partial #$t->{partialNum}"; } else { $logMsg = "full backup started for directory $t->{shareName}"; if ( $t->{incrBaseBkupNum} ne "" ) { $logMsg .= " (baseline backup #$t->{incrBaseBkupNum})"; } } } else { $incrDate = $bpc->timeStamp($t->{incrBaseTime}, 1); $logMsg = "incr backup started back to $incrDate" . " (backup #$t->{incrBaseBkupNum}) for directory" . " $t->{shareName}"; } # # A full dump is implemented with --ignore-times: this causes all # files to be checksummed, even if the attributes are the same. # That way all the file contents are checked, but you get all # the efficiencies of rsync: only files deltas need to be # transferred, even though it is a full dump. # $rsyncArgs = $conf->{RsyncArgs}; $rsyncArgs = [@$rsyncArgs, @fileList] if ( @fileList ); $rsyncArgs = [@$rsyncArgs, "--ignore-times"] if ( $t->{type} eq "full" ); $rsyncClientCmd = $conf->{RsyncClientCmd}; my $shareNameSlash = $t->{shareNameSlash}; from_to($shareNameSlash, "utf8", $conf->{ClientCharset}) if ( $conf->{ClientCharset} ne "" ); $argList = ['--server', '--sender', @$rsyncArgs, '.', $shareNameSlash]; eval { $argList = File::RsyncP->excludeStrip($argList); }; $fioArgs = { client => $t->{client}, share => $t->{shareName}, viewNum => $t->{incrBaseBkupNum}, partialNum => $t->{partialNum}, }; } # # Merge variables into $rsyncClientCmd
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -