Introduction
Dans cet article je vais tenter de vous expliquer comment mettre en place une sauvegarde distante entre un serveur de fichiers sous Windows 2008 R2 et un serveur sous linux.
Périmètre de ce tuto
Les explications qui vont suivre s’appliquent à la distribution Linux CentOS 6.4. Comme d’habitude elle devraient faire l’affaire sur une autre distrib, mais il est possible que quelques détails doivent être modifier pour que cela fonctionne. De plus, il existe plusieurs solutions pour mettre en place une sauvegarde de ce type avec rsync. Je n’en traiterai que deux. Les voici :
- Un Linux sur un site A attaquant un serveur de fichiers Windows 2008 R2 sur un site B au travers d’une liaison VPN.
- Un Linux sur un site A attaquant un Linux sur un site B au travers d’une liaison VPN, qui lui-même accède au serveur de fichiers Windows 2008 R2 du site B
Notez que je ne traiterai absolument pas des questions de VPN, de routage, etc… uniquement de rsync. Nous verrons aussi comment profiter des possibilités de versionning offertes par rsync.
Pourquoi ces deux approches ?
Simplement parce qu’en fonction du choix que vous ferez, vous pourrez ou non profiter de certaines fonctionnalités de rsync, comme :
- La synchro en mode bloc, qui vous permet de ne transférer que la partie modifiée d’un fichier déjà présent. Sympa lorsque vous sauvegardez des fichiers de plusieurs centaines de mégas qui font l’objet de fréquentes modifications d’à peine quelques kilos.
- La compression des données durant leur transfert. Sympa également pour des fichiers de base de données par exemple. Oubliez les films ou les mp3 par contre, ces données sont déjà compressées et ne le seront pas plus.
Donc hormis le cas où vous ne pouvez pas rajouter de machine sur le site B, vous auriez tort de vous priver de ces deux superbes fonctionnalités.
Première approche : Linux + Windows
Une fois votre CentOS installée, vérifiez qu’elle communique correctement avec votre serveur Windows. Si ce n’est pas le cas inutile d’aller plus loin, réglez d’abord ce problème Assurez-vous également qu’elle puisse accéder à Internet, vous en aurez besoin pour vous servir du gestionnaire de paquets.
Installer rsync
Première chose à faire, installer rsync. Voici comment faire à l’aide du gestionnaire de paquets yum :
yum -y install rsync
Construire l’arborescence de la solution
Voici l’arborescence que je vous propose :
/opt/synchro Répertoire de base de la solution /opt/synchro/current/ Répertoire accueillant vos différentes synchro /opt/synchro/current/nom_de_la_synchro1 Ce répertoire sera crée automatiquement à la première synchro /opt/synchro/current/nom_de_la_synchro2 Ce répertoire sera crée automatiquement à la première synchro /opt/synchro/logs Répertoire accueillant vos logs /opt/synchro/scripts Répertoire accueillant vos différents scripts de synchro /opt/synchro/versions Répertoire accueillant les fichiers modifiés au fil des synchro /opt/synchro/versions/nom_de_la_synchro1/AAAA-MM-JJ-HHMMSS Ce répertoire sera crée automatiquement /opt/synchro/versions/nom_de_la_synchro2/AAAA-MM-JJ-HHMMSS Ce répertoire sera crée automatiquement
Pour la crée c’est facile :
cd /opt mkdir synchro cd synchro mkdir current logs scripts versions
Le script de synchro
Il va falloir mettre en place des scripts pour la synchro. En effet, rsync seul ne sait pas le faire, il n’est que l’outils de base. Je vous demanderai d’être indulgent quant à la rédaction du code, je développe plus depuis longtemps Je vais vous le présenter par section.
La déclaration des variables
task_name="nom_de_la_tache" #Nom de la tache #de synchro (arbitraire) remote_mount_point="/mnt/synchro-"$task_name"/" #Chemin où sera monté #le partage (automatique) remote_peer="adresse_de_la_cible" #Adresse IP ou nom DNS #du serveur Windows remote_share_name="nom_du_partage_windows" #Nom du partage Windows remote_share="//"$remote_peer"/"$remote_share_name #URL du partage Windows remote_user="compte_pour_accéder_au_partage" #Compte Windows pour #accéder au partage remote_password="mot_de_passe_du_compte" #Mot de passe du compte Windows local_current_dir="/opt/synchro/current/"$task_name #Chemin local où stocker #la synchro (automatique) local_versions_dir="/opt/synchro/versions/"$task_name #Chemin local où stocker les #versions de synchro (automatique) pid=$$ #PID du process (automatique) pid_file="/var/run/"$task_name".pid" #Fichier où l'on va #stocker le PID (automatique) log_file="/opt/synchro/logs/"$task_name #Fichier de log du #script (automatique) xfer_log_file="/opt/synchro/logs/"$task_name"_"`date +%F-%H%M%S` #Fichier de log de #rsync (automatique) delta_copy=1 #Utilisation du #mode block (0=non 1=oui) compress=1 #Compression durant #les transferts (0=non 1=oui) bw_limit=1 #Limiter l'utilisation de #la bande passante (0=non 1=oui) bw_limit_rate=500 #Limite d'utilisation de #la bande passante en kbps if [ $delta_copy -eq 1 ] then delta_opts="--no-whole-file" else delta_opts="--whole-file" fi if [ $compress -eq 1 ] then compress_opts="--compress" else compress_opts="--no-compress" fi if [ $bw_limit -eq 1 ] then bw_limit_opts="--bwlimit="$bw_limit_rate else bw_limit_opts="" fi
La partie synchro
# On vérifie qu'une synchro n'est pas déjà en cours if [ -e $pid_file ] then echo `date +%F-%T`" # "$task_name" already running ! (pid="$pid")" >> $log_file exit 0 else echo $pid > $pid_file echo `date +%F-%T`" # Task "$task_name" started with pid "$pid >> $log_file fi #On écrit la liste des paramètres de synchro dans le fichier de log pour en garder une trace echo "Parameters list" >> $log_file echo "Task name "$task_name >> $log_file echo "Remote share mount point "$remote_mount_point >> $log_file echo "Remote peer "$remote_peer >> $log_file echo "Remote share "$remote_share >> $log_file echo "Remote user "$remote_user >> $log_file echo "Local sync directory "$local_current_dir >> $log_file echo "Local versionning directory "$local_versions_dir >> $log_file echo "Block mode sync "$delta_copy >> $log_file echo "Compress transfer "$compress >> $log_file echo "Bandwidth limiting "$bw_limit >> $log_file if [ $bw_limit -eq 1 ] then echo "Bandwidth limit rate "$bw_limit_rate >> $log_file fi echo "Transfer logfile "$xfer_log_file >> $log_file # On crée le point de montage, puis on monte le partage /bin/mkdir $remote_mount_point /bin/mount -t cifs $remote_share $remote_mount_point -o user=$remote_user,password=$remote_password,ro mount_error_code=$? # On vérifie que tout s'est déroulé correctement puis on lance la synchro if [ $mount_error_code -eq 0 ] then /usr/bin/rsync --archive \ --stats \ --delete \ --delete-before \ --backup \ --backup-dir=$local_versions_dir/`date +%F-%H%M%S`/ \ --log-file-format="%f %b %l %o %p %t %i" \ --log-file=$xfer_log_file $delta_opts \ --partial $compress_opts \ --ipv4 \ $bw_limit_opts \ $remote_mount_point \ $local_current_dir rsync_error_code=$? else # Ca a foiré ? On le dit et on essaye de donner une piste pour le debug echo "# Transfer FAILED !!!" >> $log_file echo "# Mount error code "$mount_error_code" !!!" >> $log_file echo "# Task aborted !!!" >> $log_file fi # On vérifie que la synchro s'est bien passée if [ $rsync_error_code -ne 0 ] then # Ca a foiré ? On le dit et on essaye de donner une piste pour le debug echo "# Rsync ERROR - Please check transfer log file !!!" >> $log_file echo "# Rsync error code "$rsync_error_code" !!!" >> $log_file fi # C'est fini, on démonte le partage et on nettoie dérrière soi /bin/umount $remote_mount_point /bin/rmdir $remote_mount_point /bin/rm $pid_file echo "# Task "$task_name" finished at "`date +%F-%T` >> $log_file
Schéma
Le fonctionnement en image :
Seconde approche : Linux + Linux + Windows
Une fois vos deux CentOS installées, vérifiez que celle du site A communique bien avec le serveur de fichier Windows, et que celle du site B communique bien avec celle du site A. Là encore si ce n’est pas le cas inutile d’aller plus loin, réglez d’abord ce problème Assurez-vous également qu’elles puissent accéder à Internet, vous en aurez besoin pour vous servir du gestionnaire de paquets.
Installer rsync, le client ssh et xinetd
Première chose à faire, installer rsync sur les deux serveurs. Voici comment faire à l’aide du gestionnaire de paquets yum :
yum -y install rsync openssh-client xinetd
Construire l’arborescence de la solution sur le serveur du site B
Voici l’arborescence que je vous propose :
/opt/synchro Répertoire de base de la solution /opt/synchro/current/ Répertoire accueillant vos différentes synchro /opt/synchro/current/nom_de_la_synchro1 Ce répertoire sera crée automatiquement à la première synchro /opt/synchro/current/nom_de_la_synchro2 Ce répertoire sera crée automatiquement à la première synchro /opt/synchro/logs Répertoire accueillant vos logs /opt/synchro/scripts Répertoire accueillant vos différents scripts de synchro /opt/synchro/versions Répertoire accueillant les fichiers modifiés au fil des synchro /opt/synchro/versions/nom_de_la_synchro1/AAAA-MM-JJ-HHMMSS Ce répertoire sera crée automatiquement /opt/synchro/versions/nom_de_la_synchro2/AAAA-MM-JJ-HHMMSS Ce répertoire sera crée automatiquement
Pour la crée c’est facile :
cd /opt mkdir synchro cd synchro mkdir current logs scripts versions
La configuration des démons rsyncd et xinetd (Serveur du site A)
Dans cette approche nous allons avoir besoin du démon rsyncd, c’est entre autre grâce à lui qui nous allons pouvoir réellement faire une synchro en mode bloc, et également profiter de la compression durant les transferts. Voici la marche à suivre :
- Activez le démon xinetd
chkconfig --add xinetd
- Éditez le fichier de configuration de rsync pour xinetd (/etc/xinetd.d/rsync) pour qu’il ressemble à ceci :
service rsync{ disable = no flags = IPv6 socket_type = stream wait = no user = root server = /usr/bin/rsync server_args = --daemon log_on_failure += USERID }
- Editez le fichier de configuration du démon rsyncd (/etc/rsyncd.conf) comme ceci :
pid file=/var/run/rsyncd.pid syslog facility=daemon[nom_de_la_tache_utilisée_dans_le_script]comment = synchro1 path = /mnt/synchro-nom_de_la_tache_utilisée_dans_le_script use chroot = yes lock file = /var/lock/rsyncd read only = yes list = yes uid = root gid = root auth users = utilisateur_du_fichier_rsyncd.secrets secrets file = /etc/rsyncd.secrets strict modes = false hosts allow = ip_du_serveur_du_site_B transfer logging = yes log format = %t: host %h (%a) %o %f (%l bytes). Total %b bytes. timeout = 120 dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz *.avi *.mp3 *.mp4 *.wmv *.mov
- Editez le fichier de compte de rsyncd (/etc/rsyncd.secrets), qui n’existe peut-être pas, comme ceci :
nom_d_utilisateur:mot_de_passe
- Attribuez les bons droits aux fichiers de configuration :
chown root.root /etc/rsyncd.* chmod 600 /etc/rsyncd.*
- Redémarrez le démon xinetd :
service xinetd restart
Générer les clefs SSH sur le serveur du site B et les copier sur le serveur du site A
Tout d’abord vous devez générer une paire de clefs ssh sur le serveur du site B :
ssh-keygen -v -f /root/.ssh/id_rsa
Puis vous devez les copier sur le serveur du site A :
ssh-copy-id -i /root/.ssh/id_rsa.pub root@ip_du_serveur_du_site_A
Le script de synchro sur le serveur du site B
Comme précédemment il va nous falloir un script pour effectuer la synchro à l’aide de rsync. Cette fois encore je vous demanderai d’être indulgent sur l’esthétique du code
La déclaration des variables
Je ne redétaillerai pas tout une seconde fois les noms parlent d’eux-même. Au pire postez vos questions
task_name="nom_de_la_tache"remote_mount_point="/mnt/synchro-"$task_name"/" remote_cifs_peer="adresse_du_serveur_windows" remote_rsync_peer="adress_du_serveur_du_site_A" remote_share_name="nom_du_partage_windows" remote_share="//"$remote_cifs_peer"/"$remote_share_name remote_rsync_module=$task_name remote_rsync_user="utilisateur_du_fichier_rsyncd.secrets" remote_rsync_password="mot_de_passe_du_fichier_rsyncd.secrets" export RSYNC_PASSWORD=$remote_rsync_password remote_cifs_user="compte_pour_accéder_au_partage_windows" remote_cifs_password="mot_de_passe_du_compte" remote_ssh_user="root" remote_ssh_ident="/root/.ssh/id_rsa"local_current_dir="/opt/synchro/current/"$task_name local_versions_dir="/opt/synchro/versions/"$task_name pid=$$ pid_file="/var/run/"$task_name".pid" log_file="/opt/synchro/logs/"$task_name xfer_log_file="/opt/synchro/logs/"$task_name"_"`date +%F-%H%M%S` delta_copy=1 compress=1 bw_limit=1 bw_limit_rate=500 if [ $delta_copy -eq 1 ] then delta_opts="--no-whole-file" else delta_opts="--whole-file" fi if [ $compress -eq 1 ] then compress_opts="--compress" else compress_opts="--no-compress" fi if [ $bw_limit -eq 1 ] then bw_limit_opts="--bwlimit="$bw_limit_rate else bw_limit_opts="" fi
La déclaration des fonctions
Cette fois-ci j’ai découpé le script en fonctions, de cette manière il sera plus facile de le faire évoluer.
function _log_to_file () { echo $* >> $log_file echo $* } function _log_parameters { _log_to_file "Parameters list" _log_to_file "Task name "$task_name _log_to_file "Remote share mount point "$remote_mount_point _log_to_file "Remote cifs peer "$remote_cifs_peer _log_to_file "Remote rsync peer "$remote_rsync_peer _log_to_file "Remote cifs share "$remote_share _log_to_file "Remote cifs user "$remote_cifs_user _log_to_file "Remote ssh user "$remote_ssh_user _log_to_file "Remote ssh key file "$remote_ssh_ident _log_to_file "Remote rsync user "$remote_rsync_user _log_to_file "Remote rsync module "$remote_rsync_module _log_to_file "Local sync directory "$local_current_dir _log_to_file "Local versionning directory "$local_versions_dir _log_to_file "Block mode sync "$delta_copy _log_to_file "Compress transfer "$compress _log_to_file "Bandwidth limiting "$bw_limit if [ $bw_limit -eq 1 ] then _log_to_file "Bandwidth limit rate "$bw_limit_rate fi _log_to_file "Transfer logfile "$xfer_log_file } function _check_instance { if [ -e $pid_file ] then _log_to_file `date +%F-%T`" # "$task_name" already running !!! (pid="$pid")" exit 1 else echo $pid > $pid_file _log_to_file `date +%F-%T`" # Task "$task_name" started with pid "$pid fi return 0 } function _init_remote_env { /usr/bin/ssh -2 -4 -i $remote_ssh_ident $remote_ssh_user@$remote_rsync_peer \ "/bin/mkdir "$remote_mount_point local error_code=$? if [ $error_code -ne 0 ] then _log_to_file _log_to_file "# Remote environment initialization FAILED !!!" _log_to_file "# Directory creation error code "$error_code" !!!" _log_to_file "# Task aborted !!!" _delete_pid_file exit 1 fi /usr/bin/ssh -2 -4 -i $remote_ssh_ident $remote_ssh_user@$remote_rsync_peer \ "/bin/mount -t cifs "$remote_share $remote_mount_point" \ -o user="$remote_cifs_user",password="$remote_cifs_password",ro" local error_code=$? if [ $error_code -ne 0 ] then _log_to_file _log_to_file "# Remote environment initialization FAILED !!!" _log_to_file "# Mount error code "$error_code" !!!" _log_to_file "# Task aborted !!!" /usr/bin/ssh -2 -4 -i $remote_ssh_ident $remote_ssh_user@$remote_rsync_peer \ "/bin/rmdir "$remote_mount_point _delete_pid_file exit 1 fi return 0 } function _start_sync { local result=0 /usr/bin/rsync --archive \ --stats \ --delete-before \ --backup \ --backup-dir=$local_versions_dir/`date +%F-%H%M%S`/ \ --log-file-format="%f %b %l %o %p %t %i" \ --log-file=$xfer_log_file $delta_opts \ --partial \ $compress_opts \ --ipv4 \ $bw_limit_opts \ $remote_rsync_user@$remote_rsync_peer::$remote_rsync_module $local_current_dir local error_code=$? if [ $error_code -ne 0 ] then _log_to_file _log_to_file "# Rsync ERROR - Please check transfer log file !!!" _log_to_file "# Rsync error code "$error_code" !!!" local result=1 fi return $result } function _rollback_remote_env { local result=0 /usr/bin/ssh -2 -4 -i $remote_ssh_ident $remote_ssh_user@$remote_rsync_peer \ "/bin/umount "$remote_mount_point local error_code=$? if [ $error_code -ne 0 ] then _log_to_file "# Remote environment rollback FAILED !!!" _log_to_file "# Unmount error code "$error_code" !!!" local result=1 fi /usr/bin/ssh -2 -4 -i $remote_ssh_ident $remote_ssh_user@$remote_rsync_peer \ "/bin/rmdir "$remote_mount_point local error_code=$? if [ $error_code -ne 0 ] then _log_to_file "# Remote environment rollback FAILED !!!" _log_to_file "# Directory destruction error code "$error_code" !!!" local result=1 fi return $result } function _delete_pid_file { /bin/rm $pid_file }
Le corps du script
_check_instance _log_parameters _init_remote_env _start_sync _rollback_remote_env_delete_pid_file _log_to_file "###### Task "$task_name" finished at "`date +%F-%T`
1 commentaire
1 ping
Cixy35
2 janvier 2014 à 17 h 02 min (UTC 1) Lier vers ce commentaire
Merci bien pour ce script, ca marche parfaitement pour ce que j’ai à faire, c’est à dire dans mon cas le 1 ! J’essaierai peut etre le 2 un des 4.
Merci encore
Sauvegarde | Pearltrees
29 août 2014 à 15 h 06 min (UTC 1) Lier vers ce commentaire
[…] Sauvegarde distante avec rsync entre windows et linux » Tutos Pour Les Nuls. Dans cet article je vais tenter de vous expliquer comment mettre en place une sauvegarde distante entre un serveur de fichiers sous Windows 2008 R2 et un serveur sous linux. […]