GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Verhalten von rsync mit Datei, die noch geschrieben wird?

Wenn Apache eine Datei irgendeiner Art an einen Ort schreibt und das Schreiben noch nicht abgeschlossen hat und dann rsync Tritt ein, rsync wird kopieren, was dort sitzt.

Das heißt, wenn Apache mit einer 5-MB-Datei arbeitet, werden nur 2 MB geschrieben und rsync einsetzt, wird die teilweise 2 MB große Datei kopiert. Diese Datei scheint also auf dem Zielserver „beschädigt“ zu sein.

Abhängig von der Größe der verwendeten Dateien können Sie den --inplace verwenden Option in rsync Folgendes tun:

Diese Option ändert, wie rsync eine Datei überträgt, wenn die Daten der Datei aktualisiert werden müssen:Anstelle der Standardmethode, eine neue Kopie der Datei zu erstellen und sie an ihren Platz zu verschieben, wenn sie fertig ist, schreibt rsync stattdessen die aktualisierten Daten direkt in die Zieldatei.

Dies hat den Vorteil, dass, wenn bei einer 5-MB-Datei beim ersten Durchlauf nur 2 MB kopiert wurden, der nächste Durchlauf bei 2 MB beginnt und die Datei weiter kopiert wird, bis die vollen 5 MB vorhanden sind.

Das Negative ist, dass es eine Situation schaffen könnte, in der jemand auf den Webserver zugreift, während eine Datei kopiert wird, und dann würde er eine Teildatei sehen. Meiner Meinung nach rsync funktioniert am besten in seinem Standardverhalten, eine „unsichtbare“ Datei zwischenzuspeichern und sie dann sofort an ihren Platz zu verschieben. Aber --inplace eignet sich gut für Szenarien, in denen große Dateien und Bandbreitenbeschränkungen dem einfachen Kopieren einer großen Datei von Anfang an im Wege stehen könnten.

Das heißt, Sie geben dies an; Hervorhebung von mir:

Alle fünf Minuten hat cron rsync ausgeführt…

Ich nehme also an, Sie haben ein Bash-Skript, um diesen Cron-Job zu verwalten? Nun, das Ding ist rsync ist intelligent genug, um nur die Dateien zu kopieren, die kopiert werden müssen. Und wenn Sie ein Skript haben, das alle 5 Minuten ausgeführt wird, scheinen Sie zu vermeiden, rsync zu haben aufeinander treten, wenn es schneller geht. Das heißt, wenn Sie es jede Minute laufen lassen, besteht die Gefahr, dass einer oder mehrere der rsync Prozesse würden aufgrund der Dateigröße oder Netzwerkgeschwindigkeit noch laufen und der nächste Prozess würde nur damit konkurrieren; eine Rennbedingung.

Eine Möglichkeit, dies zu vermeiden, besteht darin, Ihr gesamtes rsync zu umschließen Befehl in einem Bash-Skript, das nach einer Dateisperre sucht; Unten ist ein Bash-Script-Framework mit Boilerplate, das ich für solche Fälle verwende.

Beachten Sie, dass einige Leute die Verwendung von flock empfehlen werden aber seit flock auf einigen Systemen, die ich verwende, nicht installiert ist – und ich wechsle häufig zwischen Ubuntu (das es hat) und Mac OS X (das es nicht hat) – ich verwende dieses einfache Framework ohne wirkliche Probleme:

LOCK_NAME="MY_GREAT_BASH_SCRIPT"
LOCK_DIR='/tmp/'${LOCK_NAME}.lock
PID_FILE=${LOCK_DIR}'/'${LOCK_NAME}'.pid'

if mkdir ${LOCK_DIR} 2>/dev/null; then
  # If the ${LOCK_DIR} doesn't exist, then start working & store the ${PID_FILE}
  echo $$ > ${PID_FILE}

  echo "Hello world!"

  rm -rf ${LOCK_DIR}
  exit
else
  if [ -f ${PID_FILE} ] && kill -0 $(cat ${PID_FILE}) 2>/dev/null; then
    # Confirm that the process file exists & a process
    # with that PID is truly running.
    echo "Running [PID "$(cat ${PID_FILE})"]" >&2
    exit
  else
    # If the process is not running, yet there is a PID file--like in the case
    # of a crash or sudden reboot--then get rid of the ${LOCK_DIR}
    rm -rf ${LOCK_DIR}
    exit
  fi
fi

Die Idee ist dieser allgemeine Kern – wo ich echo "Hello world!" habe – ist das Herzstück Ihres Skripts. Der Rest ist im Grunde ein Sperrmechanismus/eine Logik basierend auf mkdir . Eine gute Erklärung des Konzepts finden Sie in dieser Antwort:

mkdir erstellt ein Verzeichnis, falls es noch nicht existiert, und falls doch, setzt es einen Exit-Code. Noch wichtiger ist, dass es all dies in einer einzigen atomaren Aktion erledigt, was es perfekt für dieses Szenario macht.

Also im Fall Ihres rsync Prozess, würde ich empfehlen, dieses Skript zu verwenden, indem Sie einfach den echo ändern Befehl an Ihren rsync Befehl. Ändern Sie auch LOCK_NAME zu etwas wie RSYNC_PROCESS und dann kann es losgehen.

Jetzt mit Ihrem rsync In dieses Skript eingeschlossen, können Sie den Cron-Job so einstellen, dass er jede Minute ausgeführt wird, ohne dass das Risiko einer Rennbedingung besteht, bei der zwei oder mehr rsync Prozesse kämpfen darum, dasselbe zu tun. Dadurch können Sie die Geschwindigkeit erhöhen oder rsync Aktualisierungen, die das Problem der teilweisen Übertragung von Dateien nicht beseitigen, aber den Gesamtprozess beschleunigen helfen, sodass irgendwann die vollständige Datei ordnungsgemäß kopiert werden kann.


Ja - und die Datei könnte beschädigt werden, wenn rsync die Datei liest, während gleichzeitig in die Datei geschrieben wird.

Sie können dies versuchen:https://unix.stackexchange.com/a/2558

Sie können es auch mit lsof:

skripten
lsof /path/to file

Ein Exit-Code von 0 bedeutet, dass die Datei verwendet wird, und ein Exit-Code von 1 bedeutet, dass diese Datei nicht aktiv ist.


Linux
  1. Intelligentere Dateiübertragungen als Rsync??

  2. Ist die Verwendung von Rsync während der Aktualisierung der Quelle sicher?

  3. Newline durch Nul ersetzen?

  4. Tail -f, feststellen, ob in eine Datei nicht mehr geschrieben wird?

  5. Wie kann man eine Datei ausgeben und Zeilen ignorieren, die mit „?“ beginnen?

Linux-WC-Befehl mit Beispielen

Erste Schritte mit ls

Digitale Signaturen mit GnuPG

Arbeite immer noch mit Gnome-Boxen

Feststellen, ob gerade auf die Datei geschrieben wird?

Ist mv mit Wildcard noch atomar