Атомная R-синхронизация? cron'd резервное копирование регулярно меняющегося каталога на удаленный: обеспечение одной полной резервной копии?

Атомная R-синхронизация? cron'd резервное копирование регулярно меняющегося каталога на удаленный: обеспечение одной полной резервной копии?
Атомная R-синхронизация? cron'd резервное копирование регулярно меняющегося каталога на удаленный: обеспечение одной полной резервной копии? - gradienta @ Unsplash

У меня есть каталог, который регулярно меняется, но файлы которого связаны между собой. Я хочу rsync сделать это в удаленном месте, гарантируя, что у меня всегда будет один полный набор файлов на удалении. То есть, если у меня есть одна полная резервная копия, я хочу, чтобы она сохранялась до тех пор, пока у меня не будет второй полной резервной копии, чтобы гарантировать, что любое прерывание сети не разрушит целостность первой. Если подумать, --backup не работает, потому что не будет ясно, является ли файл без резервной копии частью первой полной резервной копии или второй неполной.

Хотя то, что я хочу сделать, можно написать в сценарии, я думаю, что где-то должно быть готовое решение. Я понимаю, что rdiff-backup сделал бы это, откатив частичные резервные копии, но я не могу установить это на целевой машине. У кого-нибудь есть другие зацепки?

По-видимому, правильным термином для этого является то, что я хочу "атомарную" резервную копию. На странице --delay-updates переключатель назван "немного более атомарным", выполняющим все удаления и перемещения в самом конце. У меня сработало вот так:

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"

Хотя я не очень понимаю детали, когда man используется с --partial-dir в контексте --temp-dir, он должен быть с относительным путем.

Существует также скрипт --delay-updates в каталоге atomic-rsync. Цитирую со страницы /usr/share/rsync/scripts:

Смотрите также perl-скрипт "atomic-rsync" в поддиректории "support" для алгоритма обновления, который еще более атомарный (он использует --link-dest и параллельную иерархию файлов).

Проблема для меня заключается в том, что это только для извлечения в локальный каталог, а не для выталкивания в удаленный. Я написал сценарий, который должен выполнять эту работу правильно, ниже. После первого успешного резервного копирования man всегда будет существовать на удаленном компьютере как полная резервная копия. Прерванные резервные копии будут отображаться как <directory>, <directory>.1 и т.д. Любая из них, которая <directory>.2 завершена, будет перемещена в rsync, а остальные <directory> будут удалены.

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"

Если вы работаете с открытыми файлами, такими как база данных, прямой rsync может быть плохой идеей, так как rsync не будет читать атомарно все блоки всех файлов базы данных. Для наиболее атомарного способа потребуется система с включенными моментальными снимками. Для этого нужен выделенный раздел lvm или файловая система, такая как btrfs или zfs. Когда раздел создан, ваш rsync может свободно работать со стабильным набором файлов. --delay-updates можно использовать, чтобы сделать удаленное приложение более атомарным.


NevaDev, 9 февраля 2023 г., 00:51