rsync est un des outils les plus efficaces pour synchroniser des dossiers, que ce soit localement ou entre deux machines en réseau.

Installation

rsync est déjà pré-installé sur la plupart des distributions Linux et macOS. Pour vérifier que c’est bien le cas (macOS):

$ rsync --version
rsync  version 2.6.9  protocol version 29

Si ce n’est pas le cas, installer le paquet (Debian):

$ sudo apt-get install rsync

Utilisation

Syntaxe

Trois cas de figure possibles :

Local vers Local:  rsync [option]... [SRC]... DEST
Local vers Distant: rsync [OPTION]... [SRC]... [USER@]HOST:DEST
Distant vers Local: rsync [OPTION]... [USER@]HOST:SRC... [DEST]
  • OPTION – Les options rsync
  • SRC – Répertoire source
  • DEST – Répertoire destination
  • USER – nom d’utilisateur de la machine distante
  • HOST – adresse IP ou nom d’hôte

Options les plus courantes :

  • -a--archive. Mode archive. Synchronisation récursive des deux dossiers, préserve les liens symboliques, les dates de modifications, les groupes, les permissions, les propriétaires.
  • -z--compress. Compresse les données avant de les envoyer vers la machine distante. A utiliser si le débit vers la machine distante est bas.
  • -P. Affiche une barre de progression pendant le transfert.
  • --delete. rsync effacera les fichiers présents dans le répertoire de destination mais non présent dans le répertoire source. Idéal pour créer des miroirs, attention toutefois bien faire des tests avec l’option -n avant.
  • -n ou --dry-run. Ne fais rien, affiche simplement ce qui sera fait si la commande est exécutée sans cette option.
  • -q--quiet. Supprime les message à caractère d’information.
  • -v--verbose. Augmente le nombre de messages affichés.
  • -e. Permet d’utiliser un autre shell distant que celui par défaut (ssh).
  • -t, --times. Préserve les dates.

Exemples : local vers local

Copier un fichier d’un répertoire à un autre sans le renommer :

$ rsync -a /home/filename.zip /tmp/

Copier un fichier d’un répertoire à un autre et le renommer :

$ rsync -a /home/filename.zip /tmp/newname.zip

Synchroniser le contenu de deux répertoire locaux (si le répertoire de destination n’existe pas, il sera créé) :

$ rsync -a /var/www/html/mysite/public_html/ /var/www/html/mysite/public_html_backup/

Précisions que rsync se comportera différemment si vous précisez ou non le slash de fin /. Si le slash de fin est présent sur le répertoire source, seul le contenu du répertoire sera synchronisé. Dans le cas contraire, un répertoire sera créé dans le répertoire de destination.

Exemples : local vers distant

Inutile de préciser que rsync doit être installé sur les deux machines.

Synchroniser un dossier local (source) avec un distant (destination) :

$ rsync -a /home/nicolas/ user@host_or_ip:/home/nicolas/

Synchroniser un dossier distant (source) vers un dossier local (destination) :

$ rsync -a user@host_or_ip:/home/nicolas/ /home/nicolas/

Spécifier un port ssh différent de 22 sur la machine distante :

$ rsync -a -e "ssh -p 2322" user@host_or_ip:/home/nicolas/ /home/nicolas/

Exclure des dossiers

Exclure un dossier du répertoire source (il ne sera donc pas copié vers le répertoire de destination) :

$ rsync -a --exclude="node_modules" --exclude="tmp" /src_directory/ /dst_directory/

L’option --exclude-from permet de spécifier une liste de ressources à exclure :

$ rsync -a --exclude-from='exclude-list.txt' /src_directory/ /dst_directory/

Bien sûr, le fichier doit exister :

$ cat exclude-list.txt
node_modules
tmp

Aller plus loin

Problématique

Mon environnement de développement est constitué d’un serveur et de deux postes clients, le tout sur le même réseau. Les postes de développement ne peuvent pas exécuter du code (pas de serveur installé localement, ni même de docker qui demande beaucoup trop de ressource), c’est le rôle du serveur de développement.

Ce qui suit n’est pas à reproduire dans un environnement professionnel. Ca fonctionne ici car il n’y a qu’un seul développeur (Bibi)

Chaque projet a donc un répertoire sur le serveur de développement. Le code est donc toujours sur le serveur de développement qui lui est un vrai serveur. Voici un schéma de l’infrastructure :

Avant de lancer son IDE préféré (phpstorm), il faut donc synchroniser le répertoire local du projet avec le répertoire distant du projet. rsync arrive donc à point nommer !

Première ébauche de la commande à utiliser :

$ rsync -aP --delete nicolas@192.168.1.91:projects/xblogv7/ $HOME/PhpstormProjects/xblogv7

Là je synchronise le dossier local $HOME/PhpstormProjects/xblogv7 avec son homologue distant.
Mais un problème se pose : et si je ne veux pas synchroniser certains dossiers (comme un certain node_modules par exemple) ? Il suffit de placer la liste des dossiers à exclure dans un ficher texte et d’utiliser l’option --exclude-from :

$ rsync -aP --delete --exclude-from="excluded-files.txt" nicolas@192.168.1.91:projects/xblogv7/ $HOME/PhpstormProjects/xblogv7

Automatisation

Ce n’est pas évident à voir, mais l’utilisation de l’option --delete pose un problème : comme elle efface les dossiers qui sont présents dans destination et pas dans source, le dossier de configuration de mon IDE (qui se trouve seulement dans destination) est supprimé lors de la synchronisation… Pas très cool ça. Pour remédier à ça, on va écrire un petit script bash qui va faire une copie de ce fameux dossier avant de lancer la commande rsync, et rétablira le dossier juste après.

#!/usr/bin/env bash

# Backup IDE settings
idea_settings="${HOME}/PhpstormProjects/xblogv7/.idea"
restore=false
if [[ -e "$idea_settings" ]]
then
    echo "IDE Directory found, create a backup..."
    cp -rp "$idea_settings" "/tmp/idea"
    restore=true
fi

declare EXCLUDED_LIST
EXCLUDED_LIST[0]="public/"
EXCLUDED_LIST[1]="var/"
EXCLUDED_LIST[2]=".git/"
EXCLUDED_LIST[3]="_dev/node_modules/"

# Build excluded list
for item in "${EXCLUDED_LIST[@]}"
do
    echo "$item" >> excluded-files.txt
done

rsync -aP --delete --exclude-from="excluded-files.txt" nicolas@192.168.1.91:projects/xblogv7/ $HOME/PhpstormProjects/xblogv7

rm excluded-files.txt

# Restore IDE settings
if [ "$restore" = true ]
then
    echo "Restore backup IDE settings..."
    mkdir "$idea_settings"
    cp -rp "/tmp/idea/" "${idea_settings}"
    rm -r "/tmp/idea/"
fi

Références externes