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.
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.
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.
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