Comportement de rsync avec le fichier qui est encore en cours d'écriture?

Si Apache est au milieu de l'écriture d'un fichier volumineux et qu'un travail cran RSync s'exécute sur ce fichier, rsync tente-t-il de copier le fichier?

Exemple

  • Apache-1: Le fichier est gravé dans /var/www .
  • Apache-2: Clone d'Apache-1. Toutes les cinq minutes ont cron run rsync pour obtenir /var/www 's synched.

Si Apache écrit un fichier de quelque sorte sur un seul endroit et n'a pas terminé l'écriture , puis rsync lance, rsync copiera tout ce qui est assis là-bas.

Cela veut dire que si Apache traite un fichier de 5 Mo, seuls 2 Mo sont écrits et rsync est rsync , le fichier partiel de 2 Mo sera copié. Donc, ce fichier semble être «corrompu» sur le serveur de destination.

Selon la taille des fichiers que vous utilisez, vous pouvez utiliser l'option --inplace dans rsync pour effectuer les opérations suivantes:

Cette option modifie la façon dont rsync transfère un fichier lorsque les données du fichier doivent être mises à jour: au lieu de la méthode par défaut de créer une nouvelle copie du fichier et de la mettre en place lorsqu'il est terminé, rsync écrit plutôt les données mises à jour directement sur la destination fichier.

Le bénéfice de cela est si un fichier de 5 Mo n'a que 2 Mo copié lors de la première exécution, la prochaine tentative prendra à 2 Mo et continuera à copier le fichier jusqu'à ce que les 5 Mo complets soient en place.

Le négatif est qu'il pourrait créer une situation où quelqu'un accède au serveur Web pendant qu'un fichier est copié et alors ils verraient un fichier partiel. À mon avis, rsync fonctionne le mieux dans son comportement par défaut de la mise en cache d'un fichier "invisible" et le déplace immédiatement. Mais --inplace est bon pour les scénarios où de grands fichiers et des contraintes de bande passante pourraient --inplace un fichier volumineux de copier facilement du carré.

Cela dit, vous dites ceci; L'accent est à moi:

Toutes les cinq minutes ont cron run rsync …

Donc, je suppose que vous avez un script bash en place pour gérer ce travail cron? Bien, la chose est que rsync est suffisamment intelligent pour ne copier que les fichiers qui doivent être copiés. Et si vous avez un script qui s'exécute toutes les 5 minutes, il semble que vous essayez d'éviter que rsync marche les uns sur les autres si cela va plus vite. Autrement dit, si vous l'avez exécuté à chaque minute, il existe un risque qu'un ou plusieurs des processus rsync soient toujours en cours d'exécution en raison de la taille du fichier ou de la vitesse du réseau et le prochain processus serait juste en concurrence avec celui-ci; Une condition de course.

Une façon d'éviter cela est d'envelopper toute votre commande rsync dans un script bash qui vérifie le verrouillage d'un fichier; Ci-dessous est un cadre de script bash de Boilerplate que j'utilise pour des cas comme celui-ci.

Notez que certaines personnes recommandent l'utilisation de flock mais comme flock n'est pas installé sur certains systèmes que j'utilise, et je saute entre Ubuntu (ce qui l'a) et Mac OS X (ce qui ne l'est pas) beaucoup, j'utilise ce cadre simple sans réel problème:

 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 que le noyau général – où j'ai echo "Hello world!" C'est le cœur de votre script. Le reste est essentiellement un mécanisme de verrouillage / logique 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 si c'est le cas, il définit un code de sortie. Plus important encore, il fait tout cela dans une seule action atomique, ce qui le rend parfait pour ce scénario.

Donc, dans le cas de votre processus rsync , je recommanderais d'utiliser ce script en changeant simplement la commande echo à votre commande rsync . Aussi, changez le LOCK_NAME à quelque chose comme RSYNC_PROCESS et que vous êtes bien d'aller.

Maintenant, avec votre rsync emballé dans ce script, vous pouvez configurer le travail cron pour fonctionner chaque minute sans risque d'une condition de course où deux ou plusieurs processus rsync se battent pour faire la même chose. Cela vous permettra d'augmenter la vitesse ou les mises à jour rsync qui n'élimineront pas le problème des fichiers partiels transférés, mais cela aidera à accélérer le processus global afin que le fichier complet puisse être correctement copié à un moment donné.

Oui – et le fichier peut être endommagé si rsync lit le fichier en même temps que le fichier est écrit.

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

Vous pouvez également l'écrire avec lsof:

 lsof /path/to file 

Un code de sortie de 0 signifie que le fichier est utilisé et le code de sortie de 1 signifie qu'il n'y a pas d'activité sur ce fichier.