Synchroniser deux serveurs en temps réel avec inotify et rsync

Bonsoir 🙂

Il y a quelques jours j’avais présenté une solution de synchronisations entre deux serveurs via Rsync. Entre temps j’ai eu l’occasion d’améliorer la solution et je la partage donc ici.
La nouvelle version utilise inotify tools qui est une sorte d’observer des changements sur un repertoire de votre machine. Nous allons donc, à chaque détection, exécuter notre script de Rsync afin de lancer une synchronisation instantanée.

L’ancien article: RSYNC : synchroniser deux serveurs

Synchronisation Rsync avec système de lock

Voici donc un nouveau fichier rsync.sh qui comprend un système de lock afin d’éviter l’exécution de plusieurs instance à la fois:


#!/bin/sh

#Rsync with B server

LOG_FILE=/root/scriptsh/rsync.log
SOURCE_DIR=/var/www/mywebsite/web
DISTANT_DIR=/var/www/mywebsite
DISTANT_USER=admin
DISTANT_HOST=IP
KEY=/root/scriptsh/key.pem
LOCK_FILE=/root/scriptsh/rsync.lock

if [ -f "$LOCK_FILE" ]
then
echo "Rsync Locked !" >> $LOG_FILE
else
touch $LOCK_FILE
rsync -vrlpEogth --progress --log-file=$LOG_FILE -e "ssh -i $KEY" --rsync-path="sudo -i rsync" $SOURCE_DIR $DISTANT_USER@$DISTANT_HOST:$DISTANT_DIR
chown -R web1:client1 /var/www/mywebsite/web/*
rm $LOCK_FILE
fi

L’élément supplémentaire est donc ce if [ -f "$LOCK_FILE" ] qui vérifie la présence d’un fichier. Je crée ce fichier avec la commande touch et je le supprime ensuite. Si une instance tourne, le fichier existe et la requête est donc bloquée.

Installation de inotify tools

Simple comme bonjour 🙂
apt-get install inotify-tools

Utilisation de inotify pour déclencher rsync.sh

Nous allons créer un nouveau fichier sh à côté de rsync.sh, et celui ci va exploité inotify


#!/bin/sh

LOG=/root/scriptsh/inotify.log
DIR=/var/www/mywebsite/web
COMMAND=/root/scriptsh/rsync.sh

#Kill instance already in use (usefull if we relaunch the script by cron)
pgrep "inotify" | while read file; do kill $file; done;

while true
do
( inotifywait -r -e create $DIR >> $LOG ) && sh $COMMAND
done

Nous y avons placé un while true afin qu’inotify tourne tout le temps.
-e create dans la requêtes permet de ne filtrer que les créations (si vous aviez des modification vous auriez pu utiliser modify ou delete pour des suppressions, … ).
inotifywait --help vous permet d’obtenir toutes les informations supplémentaire.

nous avons aussi placer un système pour automatiquement killer le script si on le rappel.

! Ne lancer pas encore votre fichier

Bug courant: si votre répertoire contiens de nombreux fichier, inotify ne voudra peut être pas s’exécuter. Une erreur sera alors lancé et il faudra modifier la config
nano /proc/sys/fs/inotify/max_user_watches
Simplement augmenter la valeur donc 🙂

Mise en place d’un launcher pour inotify.sh

Si vous lancer maintenant le fichier votre console est bloqué et il est bien difficile de l’arrêter (un reboot du serveur s’impose). En effet, vous pouvez killer les process inotify mais pas le script sh avec le while true.
Pour régler ce problème, nous allons créer un autre fichier sh qui sera notre launcher et qui va s’occuper de conserver le pid du process lancer afin de pouvoir le killer si nécessaire.

Créons donc un fichier inotify_launcher.sh


#!/bin/sh

PID=/tmp/inotify_launcher.pid

kill -9 `cat $PID`
rm $PID

sh /root/scriptsh/inotify.sh 2>&1 > /dev/null &
echo $! > $PID

la première exécution va levé des erreurs car le fichier /tmp/inotify_launcher.pid n’existe pas encore, vous pouvez les ignorer.

La ligne importante ici est echo $! > $PID qui va récupéré le PID du dernier script lancé et le stocker dans le fichier.
Le début du fichier permet en cas de rappel de killé le script sh qui aura alors été lancé.

le & à la fin de la ligne exécutant le fichier sh permet de faire tourner le script en background sans bloquer la console.

Par acquis de conscience, on peut désormais ajouter un Cron supplémentaire pour relancer le launcher. Cela permet de s’assurer de deux choses: Que si le script crash il est relancé et que si le serveur reboot il sera également relancé.

crontab -e
et on y ajoute (avec placement d’un message dans les logs cron d’ISPConfig, ce qu’il y a après le | est optionnel) :
30 * * * * sh /root/scriptsh/inotify_launcher.sh 2>&1 > /dev/null | while read line; do echo `/bin/date` "Inotify relaunch" >> /var/log/ispconfig/cron.log; done

J’espère que ceci pourra vous être utile 🙂

2 réponses à “Synchroniser deux serveurs en temps réel avec inotify et rsync

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *