📄 rsync.pm
字号:
# my $args = { host => $t->{host}, hostIP => $t->{hostIP}, client => $t->{client}, shareName => $t->{shareName}, shareNameSlash => $t->{shareNameSlash}, rsyncPath => $conf->{RsyncClientPath}, sshPath => $conf->{SshPath}, argList => $argList, }; from_to($args->{shareName}, "utf8", $conf->{ClientCharset}) if ( $conf->{ClientCharset} ne "" ); from_to($args->{shareNameSlash}, "utf8", $conf->{ClientCharset}) if ( $conf->{ClientCharset} ne "" ); $rsyncClientCmd = $bpc->cmdVarSubstitute($rsyncClientCmd, $args); # # Create the Rsync object, and tell it to use our own File::RsyncP::FileIO # module, which handles all the special BackupPC file storage # (compression, mangling, hardlinks, special files, attributes etc). # $t->{rsyncClientCmd} = $rsyncClientCmd; $t->{rs} = File::RsyncP->new({ logLevel => $t->{logLevel} || $conf->{RsyncLogLevel}, rsyncCmd => sub { $bpc->verbose(0); $bpc->cmdExecOrEval($rsyncClientCmd, $args); }, rsyncCmdType => "full", rsyncArgs => $rsyncArgs, timeout => $conf->{ClientTimeout}, doPartial => defined($t->{partialNum}) ? 1 : undef, logHandler => sub { my($str) = @_; $str .= "\n"; $t->{XferLOG}->write(\$str); if ( $str =~ /^Remote\[1\]: read errors mapping "(.*)"/ ) { # # Files with read errors (eg: region locked files # on WinXX) are filled with 0 by rsync. Remember # them and delete them later. # my $badFile = $1; $badFile =~ s/^\/+//; push(@{$t->{badFiles}}, { share => $t->{shareName}, file => $badFile }); } }, pidHandler => sub { $t->{pidHandler}(@_); }, clientCharset => $conf->{ClientCharset}, fio => BackupPC::Xfer::RsyncFileIO->new({ xfer => $t, bpc => $t->{bpc}, conf => $t->{conf}, backups => $t->{backups}, logLevel => $t->{logLevel} || $conf->{RsyncLogLevel}, logHandler => sub { my($str) = @_; $str .= "\n"; $t->{XferLOG}->write(\$str); }, cacheCheckProb => $conf->{RsyncCsumCacheVerifyProb}, clientCharset => $conf->{ClientCharset}, %$fioArgs, }), }); delete($t->{_errStr}); return $logMsg;}sub run{ my($t) = @_; my $rs = $t->{rs}; my $conf = $t->{conf}; my($remoteSend, $remoteDir, $remoteDirDaemon); alarm($conf->{ClientTimeout}); if ( $t->{type} eq "restore" ) { $remoteSend = 0; ($remoteDir = "$t->{shareName}/$t->{pathHdrDest}") =~ s{//+}{/}g; ($remoteDirDaemon = "$t->{shareName}/$t->{pathHdrDest}") =~ s{//+}{/}g; $remoteDirDaemon = $t->{shareNameSlash} if ( $t->{pathHdrDest} eq "" || $t->{pathHdrDest} eq "/" ); } else { $remoteSend = 1; $remoteDir = $t->{shareNameSlash}; $remoteDirDaemon = "."; } from_to($remoteDir, "utf8", $conf->{ClientCharset}) if ( $conf->{ClientCharset} ne "" ); from_to($remoteDirDaemon, "utf8", $conf->{ClientCharset}) if ( $conf->{ClientCharset} ne "" ); if ( $t->{XferMethod} eq "rsync" ) { # # Run rsync command # my $str = "Running: " . $t->{bpc}->execCmd2ShellCmd(@{$t->{rsyncClientCmd}}) . "\n"; from_to($str, $conf->{ClientCharset}, "utf8") if ( $conf->{ClientCharset} ne "" ); $t->{XferLOG}->write(\$str); $rs->remoteStart($remoteSend, $remoteDir); } else { # # Connect to the rsync server # if ( defined(my $err = $rs->serverConnect($t->{hostIP}, $conf->{RsyncdClientPort})) ) { $t->{hostError} = $err; my $str = "Error connecting to rsync daemon at $t->{hostIP}" . ":$conf->{RsyncdClientPort}: $err\n"; $t->{XferLOG}->write(\$str); return; } # # Pass module name, and follow it with a slash if it already # contains a slash; otherwise just keep the plain module name. # my $module = $t->{shareName}; $module = $t->{shareNameSlash} if ( $module =~ /\// ); from_to($module, "utf8", $conf->{ClientCharset}) if ( $conf->{ClientCharset} ne "" ); if ( defined(my $err = $rs->serverService($module, $conf->{RsyncdUserName}, $conf->{RsyncdPasswd}, $conf->{RsyncdAuthRequired})) ) { my $str = "Error connecting to module $module at $t->{hostIP}" . ":$conf->{RsyncdClientPort}: $err\n"; $t->{XferLOG}->write(\$str); $t->{hostError} = $err; return; } $rs->serverStart($remoteSend, $remoteDirDaemon); } my $shareNameSlash = $t->{shareNameSlash}; from_to($shareNameSlash, "utf8", $conf->{ClientCharset}) if ( $conf->{ClientCharset} ne "" ); my $error = $rs->go($shareNameSlash); $rs->serverClose(); # # TODO: generate sensible stats # # $rs->{stats}{totalWritten} # $rs->{stats}{totalSize} # my $stats = $rs->statsFinal; if ( !defined($error) && defined($stats) ) { $t->{xferOK} = 1; } else { $t->{xferOK} = 0; } $t->{xferErrCnt} = $stats->{remoteErrCnt} + $stats->{childStats}{errorCnt} + $stats->{parentStats}{errorCnt}; $t->{byteCnt} = $stats->{childStats}{TotalFileSize} + $stats->{parentStats}{TotalFileSize}; $t->{fileCnt} = $stats->{childStats}{TotalFileCnt} + $stats->{parentStats}{TotalFileCnt}; my $str = "Done: $t->{fileCnt} files, $t->{byteCnt} bytes\n"; $t->{XferLOG}->write(\$str); # # TODO: get error count, and call fio to get stats... # $t->{hostError} = $error if ( defined($error) ); if ( $t->{type} eq "restore" ) { return ( $t->{fileCnt}, $t->{byteCnt}, 0, 0 ); } else { return ( 0, $stats->{childStats}{ExistFileCnt} + $stats->{parentStats}{ExistFileCnt}, $stats->{childStats}{ExistFileSize} + $stats->{parentStats}{ExistFileSize}, $stats->{childStats}{ExistFileCompSize} + $stats->{parentStats}{ExistFileCompSize}, $stats->{childStats}{TotalFileCnt} + $stats->{parentStats}{TotalFileCnt}, $stats->{childStats}{TotalFileSize} + $stats->{parentStats}{TotalFileSize}, ); }}sub abort{ my($t, $reason) = @_; my $rs = $t->{rs}; $rs->abort($reason); return 1;}sub setSelectMask{ my($t, $FDreadRef) = @_;}sub errStr{ my($t) = @_; return $RsyncLibErr if ( !defined($t) || ref($t) ne "HASH" ); return $t->{_errStr};}sub xferPid{ my($t) = @_; return ();}sub logMsg{ my($t, $msg) = @_; push(@{$t->{_logMsg}}, $msg);}sub logMsgGet{ my($t) = @_; return shift(@{$t->{_logMsg}});}## Returns a hash ref giving various status information about# the transfer.#sub getStats{ my($t) = @_; return { map { $_ => $t->{$_} } qw(byteCnt fileCnt xferErrCnt xferBadShareCnt xferBadFileCnt xferOK hostAbort hostError lastOutputLine) };}sub getBadFiles{ my($t) = @_; return @{$t->{badFiles}};}1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -