Verhalten von rsync mit Datei, die noch geschrieben wird?

Wenn Apache gerade eine große Datei schreibt und ein RSYNC-Cron-Job für diese Datei ausgeführt wird, versucht rsync, die Datei zu kopieren?

Beispiel

  • Apache-1: Die Datei wird in /var/www geschrieben.
  • [[9]] Apache-2: Klon von Apache-1. Alle fünf Minuten hat cron rsync ausgeführt, um die Synchronisierung von /var/www zu erhalten.
Author: Giacomo1968, 2014-12-03

2 answers

Wenn Apache eine Datei an einen Ort schreibt und das Schreiben nicht abgeschlossen hat und dann rsync kicks in, rsync kopiert alles, was dort sitzt.

Bedeutet, wenn Apache mit einer 5MB-Datei zu tun hat, werden nur 2MB geschrieben und rsync startet, wird die teilweise 2MB-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 die Option --inplace in rsync um Folgendes zu tun:

Diese Option ändert, wie rsync eine Datei überträgt, wenn die Daten der Datei muss aktualisiert werden: anstelle der Standardmethode zum Erstellen einer neuen kopieren Sie die Datei und verschieben Sie sie an ihren Platz, wenn sie fertig ist, rsync stattdessen schreibt die aktualisierten Daten direkt in die Zieldatei.

Der Vorteil davon ist, wenn eine 5MB-Datei beim ersten Lauf nur 2MB kopiert hat, wird der nächste Lauf bei 2MB aufgenommen und die Datei bis zum vollständigen 5MB kopiert ist vorhanden.

Das Negative ist, dass dies zu einer Situation führen kann, in der jemand auf den Webserver zugreift, während eine Datei kopiert wird, und dann eine Teildatei angezeigt wird. Meiner Meinung nach funktioniert rsync am besten im Standardverhalten, eine "unsichtbare" Datei zwischenzuspeichern und sie dann sofort an ihren Platz zu verschieben. Aber --inplace ist gut für Szenarien, in denen große Dateien und Bandbreitenbeschränkungen einer großen Datei im Wege stehen könnten, die leicht von square one kopiert werden kann.

Das heißt, Sie tun das ist meine Betonung:

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

Also nehme ich an, Sie haben ein Bash-Skript, um diesen Cron-Job zu verwalten? Nun, die Sache ist, dass rsync schlau genug ist, 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, dass rsync aufeinander tritt, wenn es schneller geht. Das heißt, wenn Sie es jede Minute ausgeführt haben, besteht die Gefahr, dass einer oder mehrere der rsync Prozesse würden aufgrund von Dateigröße oder Netzwerkgeschwindigkeit immer noch ausgeführt, und der nächste Prozess würde nur mit ihm konkurrieren.eine Rennbedingung.

Eine Möglichkeit, dies zu vermeiden, besteht darin, Ihren gesamten Befehl rsync in ein Bash-Skript einzufügen, das nach einer Dateisperre sucht.Unten ist ein Boilerplate Bash Script Framework, das ich für solche Fälle verwende.

Beachten Sie, dass einige Leute die Verwendung von flock empfehlen, aber da flock auf einigen Systemen nicht installiert ist, verwende ich-und springe zwischen Ubuntu (das hat es) und Mac OS X (was nicht) viel-ich benutze dieses einfache Framework ohne wirkliches Problem:

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, dass der allgemeine Kern-wo ich echo "Hello world!" habe-dort ist, wo das Herz deines Skripts ist. Der Rest davon ist im Grunde ein Sperrmechanismus / Logik basierend auf mkdir. Eine gute Erklärung für das Konzept ist in dieser Antwort:

Mkdir erstellt ein Verzeichnis, wenn es noch nicht existiert, und wenn es das tut, es setzt einen Exit-Code. Noch wichtiger ist, es tut all dies in Einzelzimmer atomic Action macht es perfekt für dieses Szenario.

Daher würde ich im Falle Ihres rsync - Prozesses empfehlen, dieses Skript zu verwenden, indem Sie einfach den Befehl echo in Ihren Befehl rsync ändern. Ändern Sie auch das LOCK_NAME in etwas wie RSYNC_PROCESS und dann können Sie loslegen.

Jetzt, da Ihr rsync in dieses Skript eingeschlossen ist, können Sie den Cron-Job so einstellen, dass er jede Minute ausgeführt wird, ohne das Risiko eines Rennzustands, bei dem zwei oder mehr rsync - Prozesse darum kämpfen, dasselbe zu tun Ding. Auf diese Weise können Sie die Geschwindigkeit oder die Aktualisierungen von rsync erhöhen, wodurch das Problem der Übertragung von Teildateien nicht beseitigt wird, der Gesamtprozess jedoch beschleunigt wird, sodass die vollständige Datei irgendwann ordnungsgemäß kopiert werden kann.

 22
Author: Giacomo1968,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2017-05-23 12:41:35

Ja - und die Datei kann beschädigt werden, wenn rsync ist das Lesen der Datei gleichzeitig die Datei geschrieben wird.

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

Sie können es auch mit lsof:

lsof /path/to file

Ein Exit-Code von 0 bedeutet, dass die Datei verwendet wird, und Exit-Code von 1 bedeutet, dass es keine Aktivität in dieser Datei gibt.

 3
Author: rebelshrug,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2017-04-13 12:37:10