Wenn Apache eine Datei an einen Ort schreibt und das Schreiben noch nicht abgeschlossen hat und dannrsync
einschaltet, rsync
wird alles kopiert, was sich dort befindet.
Das heißt, wenn Apache mit einer 5-MB-Datei arbeitet, werden nur 2 MB geschrieben und rsync
die Teil-2-MB-Datei wird kopiert. Diese Datei scheint also auf dem Zielserver "beschädigt" zu sein.
Abhängig von der Größe der von Ihnen verwendeten Dateien können Sie die --inplace
Option in verwenden rsync
, um Folgendes zu 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 nach Abschluss an ihren Platz zu verschieben, schreibt rsync stattdessen die aktualisierten Daten direkt in das Ziel Datei.
Dies hat den Vorteil, dass bei einer 5-MB-Datei, bei der beim ersten Durchlauf nur 2 MB kopiert wurden, der nächste Lauf bei 2 MB aufgenommen wird und die Datei weiter kopiert wird, bis die vollständigen 5 MB vorhanden sind.
Das Negative ist, dass es zu einer Situation kommen kann, in der jemand auf den Webserver zugreift, während eine Datei kopiert wird, und dann eine Teildatei sieht. Meiner Meinung nach rsync
funktioniert es am besten, wenn eine „unsichtbare“ Datei standardmäßig zwischengespeichert und dann sofort verschoben wird. Dies --inplace
ist jedoch gut für Szenarien geeignet, in denen große Dateien und Bandbreitenbeschränkungen einer großen Datei im Wege stehen, die leicht von der ersten Seite kopiert werden kann.
Das heißt, Sie sagen dies; Der Schwerpunkt liegt bei mir:
Alle fünf Minuten hat cron rsync ausgeführt…
Ich gehe also davon aus, dass Sie ein Bash-Skript eingerichtet haben, um diesen Cron-Job zu verwalten. Nun, die Sache ist rsync
klug 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, versuchen Sie anscheinend, nicht rsync
aufeinander zu treten, wenn es schneller geht. Das heißt, wenn Sie es jede Minute ausführen, besteht das Risiko, dass einer oder mehrere der rsync
Prozesse aufgrund der Dateigröße oder der Netzwerkgeschwindigkeit noch ausgeführt werden und der nächste Prozess nur im Wettbewerb damit steht. eine Rennbedingung.
Eine Möglichkeit, dies zu vermeiden, besteht darin, Ihren gesamten rsync
Befehl in ein Bash-Skript zu packen, das nach einer Dateisperre sucht. Unten ist ein Boilerplate-Bash-Skript-Framework, das ich für solche Fälle verwende.
Beachten Sie, dass einige Leute die Verwendung empfehlen, flock
aber da flock
es auf einigen von mir verwendeten Systemen nicht installiert ist - und ich viel zwischen Ubuntu (das es hat) und Mac OS X (das es nicht hat) springe - verwende ich 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, dass der allgemeine Kern - wo ich ihn habe echo "Hello world!"
- das Herz Ihres Skripts ist. Der Rest ist im Grunde ein Sperrmechanismus / eine Sperrlogik, die auf basiert mkdir
. Eine gute Erklärung des Konzepts finden Sie in dieser Antwort :
mkdir erstellt ein Verzeichnis, falls es noch nicht vorhanden ist, und legt in diesem Fall einen Exit-Code fest. Noch wichtiger ist, dass dies alles in einer einzigen atomaren Aktion erledigt wird, was es perfekt für dieses Szenario macht.
Im Falle Ihres rsync
Prozesses würde ich empfehlen, dieses Skript zu verwenden, indem Sie einfach den echo
Befehl in Ihren rsync
Befehl ändern . Ändern Sie auch das LOCK_NAME
in etwas wie RSYNC_PROCESS
und dann können Sie loslegen.
Jetzt, da Sie rsync
in dieses Skript rsync
eingebunden sind , können Sie festlegen, dass der Cron-Job jede Minute ausgeführt wird, ohne dass das Risiko einer Rennbedingung besteht, bei der zwei oder mehr Prozesse darum kämpfen, dasselbe zu tun. Auf diese Weise können Sie die Geschwindigkeit oder rsync
Aktualisierungen erhöhen, wodurch das Problem der Übertragung von Teildateien nicht beseitigt wird. Dies beschleunigt jedoch den Gesamtprozess, sodass die vollständige Datei zu einem bestimmten Zeitpunkt ordnungsgemäß kopiert werden kann.