Comportement de rsync avec un fichier en cours d’écriture?

11

Si Apache est en train d'écrire un fichier volumineux et qu'un travail cron rsync s'exécute sur ce fichier, rsync tente-t-il de copier le fichier?

Exemple

  • Apache-1: Le fichier volumineux est-il écrit? /var/www.
  • Apache-2: Clone d'Apache-1. Toutes les cinq minutes, cron lance rsync pour obtenir /var/www est synchronisé.
Louis
la source

Réponses:

16

Si Apache écrit un fichier quelconque à un endroit donné et ne l'a pas encore terminée et alors rsync coups de pied dans, rsync va copier ce qui est assis là.

Cela signifie que si Apache a affaire à un fichier de 5 Mo, seulement 2 Mo sont écrits et rsync démarre, le fichier partiel de 2 Mo sera copié. Donc, ce fichier semblerait être "corrompu" sur le serveur de destination.

Selon la taille des fichiers que vous utilisez, vous pouvez utiliser le --inplace option dans rsync faire ce qui suit:

Cette option change la manière dont rsync transfère un fichier lorsque les données du fichier   doit être mis à jour: au lieu de la méthode par défaut de créer un nouveau   copie du fichier et mise en place à la fin, rsync   à la place, écrit les données mises à jour directement dans le fichier de destination.

L'avantage de ceci est que si un fichier de 5 Mo a seulement 2 Mo copiés lors de la première utilisation, la prochaine exécution sera prise à 2 Mo et continuera à copier le fichier jusqu'à ce que les 5 Mo complets soient en place.

L'inconvénient est que cela pourrait créer une situation dans laquelle une personne accède au serveur Web pendant la copie d'un fichier et voit alors un fichier partiel. À mon avis rsync fonctionne mieux dans son comportement par défaut consistant à mettre en cache un fichier «invisible», puis à le déplacer immédiatement. Mais --inplace convient aux scénarios où des fichiers volumineux et des contraintes de bande passante peuvent empêcher un fichier volumineux d'être facilement copié depuis le début.

Cela dit, vous déclarez ceci; L'accent est à moi:

Toutes les cinq minutes cron a lancé rsync…

Donc, je suppose que vous avez un script bash en place pour gérer ce travail cron? Eh bien, la chose est rsync est suffisamment intelligent pour ne copier que les fichiers à copier. Et si vous avez un script qui s'exécute toutes les 5 minutes, il semble que vous essayez d'éviter d'avoir rsync marchez les uns sur les autres si ça va plus vite. Cela signifie que si vous le courez toutes les minutes, il existe un risque qu’un ou plusieurs des rsync les processus seraient toujours en cours d'exécution en raison de la taille du fichier ou de la vitesse du réseau et le processus suivant serait simplement en concurrence avec celui-ci; une condition de course.

Une façon d’éviter cela est d’envelopper tout votre rsync commande dans un script bash qui recherche un verrou de fichier; Vous trouverez ci-dessous un framework de script bash que j'utilise dans de tels cas.

Notez que certaines personnes recommanderont d’utiliser flock mais depuis flock n’est pas installé sur certains systèmes que j’utilise - et j’ai beaucoup de sauts entre Ubuntu (qui le possède) et Mac OS X (qui ne le fait pas beaucoup) - j’utilise ce cadre simple sans problème réel:

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

L’idée est ce noyau général — où j’ai echo "Hello world!" - est où le coeur de votre script est. Le reste est essentiellement un mécanisme / logique de verrouillage basé sur mkdir. Une bonne explication du concept est dans cette réponse :

mkdir crée un répertoire s'il n'existe pas encore, et s'il existe,   il définit un code de sortie. Plus important encore, il fait tout cela en un seul   action atomique le rendant parfait pour ce scénario.

Donc dans le cas de votre rsync processus, je recommanderais d’utiliser ce script en changeant simplement le echo commande à votre rsync commander. Aussi, changez le LOCK_NAME à quelque chose comme RSYNC_PROCESS et puis vous êtes prêt à partir.

Maintenant avec votre rsync encapsulé dans ce script, vous pouvez configurer le travail cron pour qu'il s'exécute toutes les minutes sans risque rsync les processus se battent pour faire la même chose. Cela vous permettra d’augmenter la vitesse ou rsync mises à jour qui n'élimineront pas le problème des fichiers partiels en cours de transfert, mais qui contribueront à accélérer le processus global afin que le fichier complet puisse être copié correctement à un moment donné.

JakeGould
la source
1
Merci de nous avoir signalé la possibilité que plusieurs rsyncs soient exécutés, n’y avez pas pensé. Le script sonne bien. J'essayais simplement de comprendre les pièges de la synchronisation d'un site à charge équilibrée avec rsync, et cela semble les alléger. Bonus merveilleux. J'ai toujours l'impression que c'est peut-être la mauvaise approche ... mais voyons :)
Louis
@Louis vous êtes les bienvenus! En outre, si vous souhaitez que les dossiers restent synchronisés en fonction des modifications immédiates des fichiers, je vous recommande vivement de vous pencher sur l’utilisation de / adapting. lsyncd. Il vous permet d’avoir des «dossiers actifs» qui tiennent vraiment compte de leur activité, puis d’agir sur ces fichiers lorsque des modifications sont apportées. j'utilise rsync beaucoup comme indiqué dans ma réponse, mais j'utilise lsyncd pour les cas nécessitant une forme d'action non cron / plus immédiate.
JakeGould
3

Oui - et le fichier peut être corrompu si rsync le lit en même temps que le fichier.

Vous pouvez essayer ceci: https://unix.stackexchange.com/a/2558

Vous pouvez également le script avec lsof:

lsof /path/to file

Un code de sortie de 0 signifie que le fichier est en cours d'utilisation et un code de sortie de 1 signifie qu'il n'y a aucune activité sur ce fichier.

rebelshrug
la source