原子 Rsync?定期将目录更改为远程的 cron 备份:确保一次完整的备份?

原子 Rsync?定期将目录更改为远程的 cron 备份:确保一次完整的备份?

我有一个目录,它经常更改,但其文件是相关的。我想将rsync其保存到远程位置,以确保我在远程位置始终拥有一套完整的文件。也就是说,如果我有一个完整的备份,我希望将其保存到我有第二个完整的备份,以确保任何网络中断都不会破坏第一个备份的完整性。如果你仔细想想,这是--backup行不通的,因为不清楚未备份的文件是第一个完整备份的一部分,还是第二个不完整备份的一部分。

虽然我想要做的事情是可以编写脚本的,但我认为肯定有现成的解决方案。我知道rdiff-backup可以做到这一点,回滚部分备份,但我无法在目标机器上安装它。有人有其他线索吗?

答案1

如果您使用打开的文件(如数据库),直接读取rsync可能不是一个好主意,因为rsync它不会自动读取数据库中所有文件的所有块。最原子的方式需要一个启用了快照的系统。这需要一个专用分区,或像或 这样lvm的文件系统。当对分区进行快照时,您可以自由地处理一组稳定的文件。 可用于制作远程应用程序btrfszfsrsync--delay-updates更多的原子。

答案2

显然,正确的术语是我想要一个“原子”备份。页面--delay-updates中的开关被称为man“更原子”,在最后执行所有删除和移动。它对我来说很有效,如下所示:

HOME="/home/me"
BACKUPFOLDER="$HOME/Backup/"
DIRECTORYLOG="$BACKUPFOLDER/<directory>.log"

NICERSYNC="nice -n 19 ionice -c 3 /usr/bin/rsync"
REMOTEHOST="[email protected]"
REMOTEBACKUPFOLDER="/home/me/Backup"

# partial-dir must be relative when using it with temp-dir
RSYNCSWITCHES="-acv --itemize-changes --delay-updates --delete-delay --partial-dir=<directory>-partial --temp-dir=$REMOTEBACKUPFOLDER/<directory>-temp"

$NICERSYNC $RSYNCSWITCHES "$BACKUPFOLDER/<directory>" $REMOTEHOST:\"$REMOTEBACKUPFOLDER\" &>> "$DIRECTORYLOG"

虽然我不太明白细节,但当--partial-dir与 一起使用--temp-dir--delay-updates,需要给定相对路径

atomic-rsync目录中还有一个脚本/usr/share/rsync/scripts。引用自man页面:

另请参阅“support”子目录中的“atomic-rsync”perl 脚本,了解更加原子的更新算法(它使用--link-dest 和并行文件层次结构)。

对我来说,问题是,这只能拉到本地目录,而不是推送到远程目录。我编写了一个可以正确完成这项工作的脚本,如下所示。第一次成功备份后,<directory>将始终作为完整备份存在于远程。中断的备份将显示为<directory>.1<directory>.2等。任何rsync已完成的备份都将移动到<directory>,另一个<directory>.n将被删除。

HOME="/home/me"
BACKUPFOLDER="$HOME/Backup/<directory>"
DIRECTORYLOG="$BACKUPFOLDER/<directory>.log"

LOCALFOLDER="/home/dev/Backup"
LOCALSUBFOLDER="Restic/<directory>"
LOCALSOURCE="$LOCALFOLDER/$LOCALSUBFOLDER"

REMOTEHOST="[email protected]"
REMOTEHOME="/home/me"
REMOTEFOLDER="Backup"
REMOTESUBFOLDER="<directory>"
REMOTETARGET="$REMOTEFOLDER/$REMOTESUBFOLDER"

NICERSYNC="nice -n 19 ionice -c 3 /usr/bin/rsync"
SWITCHES="-ac --partial-dir=\"$REMOTEHOME/$REMOTETARGET-partial\""

errormsgandexit() {
    if [[ $1 -ne 0 ]]; then
        echo "$2"
        exit $1
    fi
}

ssherrormsgandexit() {
    SSHCONNECTERROR=255
    if [[ $1 -eq $SSHCONNECTERROR ]]; then
        echo "$2"
        exit $1
    fi
}

echo -e "\n$(date) Rsync <directory>\n--------------------" >> "$DIRECTORYLOG"

# If TARGET exists, we use that for links: 
ssh $REMOTEHOST "[[ -d \"$REMOTETARGET\" ]]" && SWITCHLINKS="--link-dest=\"$REMOTEHOME/$REMOTETARGET\""
ssherrormsgandexit $? "ssh connect failure while checking $REMOTETARGET directory." >> "$DIRECTORYLOG" 

# Find the smallest n such that TARGET.n doesn't exist. use TARGET.1-(n-1) for links.
declare -i n=1
while ssh $REMOTEHOST "[[ -d \"$REMOTETARGET.$n\" ]]"; ! ((RETURN=$?)); do
    SWITCHLINKS="$SWITCHLINKS --link-dest=\"$REMOTEHOME/$REMOTETARGET.$((n++))\""
done
ssherrormsgandexit $RETURN "ssh connect failure while checking $REMOTETARGET.$n directory." >> "$DIRECTORYLOG" 

SWITCHESLINKS="$SWITCHES $SWITCHLINKS"

# now I am free to copy to TARGET.n:
$NICERSYNC $SWITCHESLINKS "$LOCALSOURCE/" $REMOTEHOST:\"$REMOTETARGET.$n\" >> "$DIRECTORYLOG"
errormsgandexit $? "rsync error, code $?." # >> "$DIRECTORYLOG" 

# if rsync was successful, just keep the most recent complete TARGET
ssh $REMOTEHOST "([[ ! -d \"$REMOTETARGET\" ]] || rm -r \"$REMOTETARGET\") && \
                mv \"$REMOTETARGET.$n\" \"$REMOTETARGET\" && \
                ([[ ! -d \"$REMOTETARGET.1\" ]] || rm -r \"$REMOTETARGET.\"*)" >> "$DIRECTORYLOG"
RETURN=$?
ssherrormsgandexit $RETURN "ssh connect failure while reordering $REMOTETARGET\* directories." >> "$DIRECTORYLOG"
errormsgandexit $RETURN "error when reorganizing $REMOTETARGET* directories." >> "$DIRECTORYLOG"

相关内容