GNU/Linux >> Tutoriels Linux >  >> Linux

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

Si Apache écrit un fichier quelconque à un endroit et n'a pas terminé de l'écrire puis rsync démarre, rsync copiera tout ce qui est assis là.

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

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

Cette option modifie la manière 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 consistant à créer une nouvelle copie du fichier et à la mettre en place lorsqu'elle est terminée, rsync écrit à la place les données mises à jour directement dans le fichier de destination.

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

L'inconvénient est que cela pourrait créer une situation dans laquelle quelqu'un accède au serveur Web pendant la copie d'un fichier, puis verrait un fichier partiel. A mon avis rsync fonctionne mieux dans son comportement par défaut de mise en cache d'un fichier "invisible" puis de le mettre en place immédiatement. Mais --inplace est bon pour les scénarios où les fichiers volumineux et les contraintes de bande passante peuvent empêcher la copie facile d'un fichier volumineux à partir de la case départ.

Cela dit, vous déclarez ceci; l'accent est mis sur moi :

Toutes les cinq minutes a cron exécuté rsync…

Donc, je suppose que vous avez un script bash en place pour gérer ce travail cron ? Eh bien, le truc est rsync est assez 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 d'avoir rsync marcher l'un sur l'autre si ça va plus vite. Cela signifie que si vous l'exécutez toutes les minutes, il y a 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 lui ; 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 ; ci-dessous est un framework de script bash passe-partout que j'utilise pour des cas comme celui-ci.

Notez que certaines personnes recommanderont d'utiliser flock mais depuis flock n'est pas installé sur certains systèmes que j'utilise - et je saute souvent entre Ubuntu (qui l'a) et Mac OS X (qui n'en a pas) - j'utilise ce framework 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 ce noyau général, où j'ai echo "Hello world!" - est là où se trouve le cœur de votre script. Le reste est essentiellement un mécanisme/logique de verrouillage basé sur mkdir . Une bonne explication du concept se trouve 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 en une seule action atomique, ce qui le rend 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 commande. Changez également le LOCK_NAME à quelque chose comme RSYNC_PROCESS et alors vous êtes prêt à partir.

Maintenant avec votre rsync enveloppé dans ce script, vous pouvez configurer la tâche cron pour qu'elle s'exécute toutes les minutes sans aucun risque de condition de course où deux ou plusieurs 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 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 corrompu si rsync lit le fichier en même temps que le fichier est en cours d'écriture.

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

Vous pouvez également le scripter 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.


Linux
  1. Des transferts de fichiers plus intelligents que Rsync ?

  2. L'utilisation de Rsync pendant la mise à jour de la source est-elle sûre ?

  3. Remplacer la nouvelle ligne par Nul ?

  4. Comment générer un fichier et ignorer les lignes commençant par "?" ?

  5. Autorisations de fichiers sous Linux avec exemple

Commande Linux WC avec exemples

Démarrer avec ls

Signatures numériques avec GnuPG

Travaille toujours avec des boîtes de gnome

Déterminez si le fichier est en cours d'écriture ?

Est-ce que mv avec joker est toujours atomique