Script shell pour synchroniser vos fichiers sur FTP

Introduction

Il y a quelques semaines, j'ai eu besoin de créer un script permettant de synchroniser mes fichiers locaux vers un serveur FTP.

En effet, je possède sur OVH un serveur mutualisé bas de gamme qui me permet d'héberger quelques sites. Le soucis est que je ne peux mettre à jour mes fichiers seulement via FTP. Je ne peux donc pas réellement utiliser un système de versions comme GIT ou SVN.

Jusqu'à maintenant, je me débrouillais pour faire sans, sauf que ça devient de plus en plus utile d'utiliser ce genre d'outil. J'ai donc opté pour utiliser GitHub et un script shell qui va ensuite synchroniser mon FTP en fonction de mes modifications.

Découverte de lftp

J'étais donc parti pour me créer mon propre script, jusqu'à ce que je découvre lftp. Il permet de transférer des fichiers sur un serveur via FTP (et quelques autres protocoles) en ligne de commande.

Ce qui m'a surtout intéressé, c'est sa fonctionnalité mirror, qui permet de synchroniser votre code local et votre code distant :

1 $> lftp "ftp://ftp_user:ftp_pass@ftp_host" -e "mirror -R -e path_local path_remote ; quit"
  • ftp_user, ftp_pass, ftp_host : Vos identifiants FTP.
  • -e de lftp : Spécifie une commande à exécuter.
  • mirror : Commande permettant de synchroniser des fichiers entre le serveur et la version locale.
  • -R de mirror : Par défaut, lftp est utilisé pour récupérer des fichiers sur le serveur, et mettre à jour notre version locale. Ici, nous souhaitons faire l'inverse ; c'est l'utilité de cette option : inverser la commande mirror.
  • -e de mirror : Indique qu'il faut supprimer les fichiers distants s'ils n'existent pas dans la version locale.
  • path_local de mirror : Votre chemin vers votre version locale.
  • path_remote de mirror : Votre chemin distant. Un détail important : "If the target directory ends with a slash (except the root), the source base name is appended to target directory name."
  • quit : Commande permettant d'indiquer qu'il faut fermer la connexion une fois la synchronisation effectuée.

Aller plus loin avec lftp

Il existe tout un tas d'autres options à lftp ainsi qu'à la sous-commande mirror.

Par exemple, une autre option qui m'a été utile pour mon script est l'exclusion de certains dossiers/fichiers lors de la synchronisation :

  • .git/, .svn/ : Ces dossiers utilisés par votre système de versions ne doivent surtout pas être rendus publiques.
  • Vos dossiers de cache ne doivent pas non plus être remplacé/supprimé, il faut les ignorer.
  • Idem pour vos dossiers d'upload, si vous ne les ignorez pas, le contenu de ces dossiers seront supprimés.
  • ...

Pour cela, il suffit de rajouter l'option -x à la commande mirror, suivi du dossier/fichier que vous souhaitez exclure de la synchronisation (donc, s'il le rencontre, que ce soit sur le serveur distant ou en local, il sera ignoré). Cette option peut bien entendu être utilisé plusieurs fois.

Une autre option dont je me suis servi : verbose, permettant donc de savoir exactement ce que lftp fait :

1 Verbosity level can be selected using --verbose=level option or by several -v options, e.g. -vvv. Levels are:
2 - 0 - no output (default)
3 - 1 - print actions
4 - 2 - +print not deleted file names (when -e is not specified)
5 - 3 - +print directory names which are mirrored

Vous trouverez la liste des autres sous-commandes et options sur le site officiel : man lftp.

Script de synchronisation

Voici donc un petit script shell utilisant lftp :

 1 #!/bin/sh
 2 
 3 # Configurations Access FTP
 4 
 5 ftp_user="username"
 6 ftp_pass="password"
 7 ftp_host="ftp.mon-site.com"
 8 
 9 # Configurations Update
10 
11 path_local="`pwd`/"
12 path_remote="/"
13 excludes=(".git/" "saves/" "www/caches/" "www/upload/")
14 
15 # Initialisation Update
16 
17 s_excludes=""
18 for (( i_exclude=0; i_exclude < ${#excludes[@]}; ++i_exclude ))
19 do
20     s_excludes="${s_excludes}-x ${excludes[$i_exclude]} "
21 done
22 
23 # Start Update
24 
25 lftp "ftp://${ftp_user}:${ftp_pass}@${ftp_host}" -e "mirror --verbose=3 -e -R ${s_excludes} ${path_local} ${path_remote} ; quit"

À vous ensuite de choisir quand exécuter ce script. Si vous souhaitez le lancer manuellement, il pourrait être utile de rajouter avant l'appel à la commande lftp un git pull (ou svn up). Inversement, si vous souhaitez exécuter ce script à chaque commit, vous pourriez par exemple utiliser votre script sh comme un hook de GIT, de façon à ce qu'il soit exécuté à chaque fois sans que vous ayez besoin de vous en souciez.


FTP Shell

Article publié le 19 Juin 2014.

Commentaires