rsync-Verzeichnis, sodass alle Änderungen atomar angezeigt werden

8

Ich mache einige nächtliche und wöchentliche Spiegelungen häufig verwendeter Repositorys für das lokale Netzwerk. In einigen Fällen hat jemand versucht, ein Update durchzuführen, während der Rsync ausgeführt wird, und ist fehlgeschlagen, da die erwarteten Dateien noch nicht alle vorhanden sind.

Ist es möglich, einen rsync so durchzuführen, dass alle geänderten Dateien nach Abschluss nur mit den richtigen Namen angezeigt werden? Ich weiß, dass rsync während jeder Übertragung temporäre .hidden-Dateien verwendet, aber kann ich die Umbenennung verschieben, bis sie irgendwie abgeschlossen ist?

Alternativ könnte ich die Option --backup verwenden, um alle Änderungen in ein Verzeichnis zu verschieben und sie anschließend atomar zu verschieben, aber ich möchte, dass die Funktion umgekehrt funktioniert wie jetzt.

Ich bin auf Linux für das, was es wert ist.

Mikebabcock
quelle

Antworten:

4

Sie können die --link-dest=Option verwenden. Grundsätzlich würden Sie einen neuen Ordner erstellen, alle Dateien sind fest mit dem neuen verknüpft. Wenn alles erledigt ist, können Sie einfach die Ordnernamen austauschen und den alten entfernen.

Es ist unmöglich, dies zu 100% atomar unter Linux zu tun, da es keine Kernel / VFS-Unterstützung dafür gibt. Das Austauschen der Namen ist jedoch nur 2 Systemaufrufe entfernt, sodass der Vorgang weniger als 1 Sekunde dauern sollte. Dies ist nur unter Darwin (MAC / OSX) mit dem Systemaufruf "Exchangeedata" auf HFS-Dateisystemen möglich.

Florin Asăvoaie
quelle
4

Ich mache etwas Ähnliches mit rsyncBackups [auf Festplatte] und habe das gleiche Problem festgestellt, weil ein Daemon Dateien aktualisiert, während das Backup ausgeführt wird.

Im Gegensatz zu vielen anderen Programmen weist rsync viele verschiedene Fehlercodes auf [siehe Manpage unten]. Von Interesse sind zwei:

23 - Teilübertragung aufgrund eines Fehlers
24 - Teilübertragung aufgrund verschwundener Quelldateien

Wenn rsync eine Übertragung durchführt und auf eine dieser Situationen stößt, wird es nicht sofort gestoppt. Es überspringt und fährt mit den Dateien fort, die es übertragen kann . Am Ende wird der Rückkehrcode angezeigt.

Wenn Sie also den Fehler 23/24 erhalten, führen Sie einfach den rsync erneut aus. Die nachfolgenden Läufe gehen viel schneller und übertragen normalerweise nur die fehlenden Dateien aus dem vorherigen Lauf. Schließlich erhalten Sie einen sauberen Lauf.

Um atomar zu sein, verwende ich während der Übertragung ein "tmp" -Dir. Wenn dann rsync run sauber ist, benenne ich es [atomar] in um<date>

Ich benutze auch die --link-destOption, aber ich benutze sie, um Delta-Backups zu erstellen (z. B. --link-dest=yesterdaytäglich).

Obwohl ich es selbst nicht verwendet habe, --partial-dir=DIRkann es sein, dass die versteckten Dateien das Sicherungsverzeichnis nicht überladen. Stellen Sie sicher, dass sich DIR im selben Dateisystem wie Ihr Sicherungsverzeichnis befindet, damit die Umbenennung atomar ist

Während ich dies in Perl mache, habe ich ein Skript geschrieben, das das, was ich gesagt habe, mit etwas mehr Details / Präzision für Ihre spezielle Situation zusammenfasst. Es ist in tcsh-ähnliche Syntax, [ungetestet und ein wenig rau], aber es als Pseudo-Code behandeln Ihre eigenen zu schreiben bash, perl, pythonSkript , wie Sie wählen. Beachten Sie, dass es keine Begrenzung für Wiederholungsversuche gibt, aber Sie können dies ganz einfach nach Ihren Wünschen hinzufügen.

#!/bin/tcsh -f
# repo_backup -- backup repos even if they change
#
# use_tmp -- use temporary destination directory
# use_partial -- use partial directory
# use_delta -- make delta backup

# set remote server name ...
set remote_server="..."

# directory on server for backups
set backup_top="/path_to_backup_top"
set backup_backups="$backup_top/backups"

# set your rsync options ...
set rsync_opts=(...)

# keep partial files from cluttering backup
set server_partial=${remote_server}:$backup_top/partial
if ($use_partial) then
    set rsync_opts=($rsync_opts --partial-dir=$server_partial)
endif

# do delta backups
if ($use_delta) then
    set latest=(`ssh ${remote_server} ls $backup_backups | tail -1`)

    # get latest
    set delta_dir="$backup_backups/$latest"

    if ($#latest > 0) then
        set rsync_opts=($rsync_opts --link-dest=${remote_server}:$delta_dir)
    endif
endif

while (1)
    # get list of everything to backup
    # set this to whatever you need
    cd /local_top_directory
    set transfer_list=(.)

    # use whatever format you'd like
    set date=`date +%Y%m%d_%H%M%S`

    set server_tmp=${remote_server}:$backup_top/tmp
    set server_final=${remote_server}:$backup_backups/$date

    if ($use_tmp) then
        set server_transfer=$server_tmp
    else
        set server_transfer=$server_final
    endif

    # do the transfer
    rsync $rsync_opts $transfer_list $server_transfer
    set code=$status

    # run was clean
    if ($code == 0) then
        # atomically install backup
        if ($use_tmp) then
            ssh ${remote_server} mv $backup_top/tmp $backup_backups/$date
        endif
        break
    endif

    # partial -- some error
    if ($code == 23) then
        continue
    endif

    # partial -- some files disappeared
    if ($code == 24) then
        continue
    endif

    echo "fatal error ..."
    exit(1)
end
Craig Estey
quelle
Sie scheinen einen Streuner (oder Vermissten) '"'inset backup_backups=$backup_top/backups"
David C. Rankin
@ DavidC.Rankin Hallo David. Ja, behoben. [aber ich habe mich als "rau" vorqualifiziert ;-)]. Aber danke, dass du dem Link unter meiner SO-Antwort gefolgt bist. Ich habe schon andere solche Links gemacht, aber Sie sind der erste, der eine positive Bestätigung dafür gibt, dass jemand ihnen tatsächlich folgt :-)
Craig Estey
Oh ja, keine große Sache. Ich war wirklich neugierig, wie Sie Ihre Inkrementelle eingerichtet haben. Ich habe rsyncmeine Office-Backups verwaltet (na ja ... seit 2001 (oder 2)) und ich schaue mir immer die verschiedenen Arten an, wie Leute mit ihren umgehen. Ich mag das.
David C. Rankin
@ DavidC.Rankin Es ist ziemlich ähnlich. Für mehrere Hosts : set backup_backups="$backup_top/backups/<host_to_backup>". Das Skript wird auf diesem Host ausgeführt. Zuerst tune2fs -lwird "Dateisystemstatus" verwendet, um festzustellen, ob der FS Fehler aufweist (dh benötigt fsck), und die Ausführung wird abgelehnt, wenn dies der Fall ist . Der Name jedes Sicherungslaufwerks ist eine Farbe (z. B. Kupfer, Indigo usw.). Ich feuere auf jedem System einen Launcher an und sie stellen eine Zeit ein (z. B. 10:09 -> 10:15), damit sie alle genau zur gleichen Zeit feuern (gibt dem Besitzer Zeit, mit Mittag wieder einzusteigen). Auf diese Weise hat jedes System genau den gleichen Zeitstempel für die Sicherung
Craig Estey
@ DavidC.Rankin Der Launcher löst rsync in einem xterm-Fenster mit der Hintergrundfarbe der Laufwerksfarbe aus. Es ist hübsch, aber ich habe zwei Systeme und vier bkup-Laufwerke. Wenn ich also bkup all sys auf allen Laufwerken sage, hilft es. Der gemeinsame Zeitstempel ermöglicht den "Zustand der Welt" zum Zeitpunkt X. Ich mache das nicht, aber mehrere Umdrehungen des Laufwerks zum externen Safe. Sichern Sie [von allen Systemen] für einen bestimmten Tag auf einem bestimmten Laufwerk [drehen]. Schließlich haben Laufwerke wie N Monate Deltas. Gelegentlich rm die älteren für Platz. Ich verwende WD-MyBook (4 TB) USBs, daher habe ich ein Jahr lang keinen Platz mehr benötigt.
Craig Estey
1

Ich bin mir nicht sicher, ob dir das helfen wird, aber ...

Wenn es Ihnen nichts ausmacht, jedes Mal den gesamten Datensatz zu kopieren, und wenn Sie Symlinks verwenden können, um auf das Zielverzeichnis zu verweisen, sollten Sie in der Lage sein, alles in ein temporäres Verzeichnis zu synchronisieren und dann das alte und das neue auszutauschen ( umzubenennen () ) Symlinks atomar, wie folgt:

% mkdir old_data new_data
% ln -s old_data current
% ln -s new_data new
% strace mv -T new current

was läuft

rename("new", "current") = 0

und gibt

current -> new_data

Selbst damit dies funktioniert, sollten Clients, die versuchen, aus diesem Setup zu lesen, cdin das Verzeichnis, auf das der Symlink verweist, bevor sie Lesevorgänge ausführen. Andernfalls besteht die Gefahr, dass einige Teile des Codes / der Daten aus der alten und einige aus der neuen Kopie geladen werden.

Karol Nowak
quelle
Ich verwende einen ähnlichen Algorithmus (Kopie in einen neuen Directowy + Change-Symlink mit dem Namen current ) mit meinem Installationsskript für PHP-Webanwendungen, auch auf Produktionsservern. Dies ist eine gute Lösung, die minimale Ausfallzeiten und vollständig atomare Verfahren ermöglicht.
sam_pan_mariusz
1

Sind die Spiegelsynchronisierungen automatisch (eine Cron- Aufgabe oder ähnliches)? Wenn ja, verwenden Sie wahrscheinlich einen dedizierten Betriebssystembenutzer, habe ich Recht? Die Lösung könnte also sein, anstatt einfach zu kopieren:

  1. Legen Sie die Zielverzeichnisberechtigungen so fest, dass nur rsync darauf zugreifen kann.
  2. Fahren Sie mit der Synchronisierung fort.
  3. Ändern Sie die Berechtigungen des Ziels (unbedingt), damit die anderen erneut darauf zugreifen können.

Der Nachteil ist, dass während des Synchronisierungsvorgangs (nicht sicher, wie lange es dauert) auf das Zielverzeichnis nicht zugegriffen werden kann. Sie müssen selbst entscheiden, ob es hier in Ordnung ist.

sam_pan_mariusz
quelle