Unison : synchronisation de données

Bonjour à tous ! 3 mots sur un outil qui permet de synchroniser deux espaces de données : Unison. Son intérêt peut paraître très relatif, notamment en comparaison de protocoles plus utilisés et plus aboutis comme RSync, toujours est-il qu'il est capable de créer et de maintenir 2 réplications de données, qu'elles soient locales (ou montées) ou distantes accessibles en SSH, et de gérer les modifications source vers destination ou bien destination vers source. Pourquoi ne pas faire un détour ?

Installation from src

Comme d'habitude, partons des sources. A l'heure où j'écris ces lignes, nous en sommes à la 2.40.61, donc l'installation se basera sur cette version. Attention à corriger lors de la parution d'une version supérieure.
$ cd /usr/local/src/ & wget http://www.seas.upenn.edu/~bcpierce/unison//download/releases/stable/unison-2.40.61.tar.gz

$ tar zxf unison-2.40.61.tar.gz

$ cd unison-2.40.61

$ make mkProjectInfo

$ make
Le make install a planté sur la copie du binaire sous ~/bin/ (pour la simple et bonne raison que ~/bin n'existe pas). Pour résoudre le problème, il faut modifier le Makefile, et notamment la ligne 82. En commenté, le répertoire qui doit contenir les binaires est mis à ~/bin par défaut. En le mettant à /usr/local/bin, c'est tout de suite plus propre...
#INSTALLDIR = $(HOME)/bin/

INSTALLDIR = /usr/local/bin
Le / manquant implique une autre modification, ligne 95 :
# cp $(NAME)$(EXEC_EXT) $(INSTALLDIR)$(NAME)-$(MAJORVERSION)$(EXEC_EXT)

cp $(NAME)$(EXEC_EXT) $(INSTALLDIR)/$(NAME)-$(MAJORVERSION)$(EXEC_EXT)
$ make install
mv /usr/local/src/unison-2.40.61 /tmp/unison-7838
cp unison /usr/local/bin/unison
cp unison /usr/local/bin/unisonunison-2.40
Nous avons fini l'installation. Pour avoir une idée des options disponible, il suffit de faire appel au traditionnel -help.
$ /usr/local/bin/unison -help
Usage: unison [options]
or unison root1 root2 [options]
or unison profilename [options]

Basic options:
-auto              automatically accept default (nonconflicting) actions
-batch             batch mode: ask no questions at all
-doc xxx           show documentation ('-doc topics' lists topics)
-fat               use appropriate options for FAT filesystems
-group             synchronize group attributes
-ignore xxx        add a pattern to the ignore list
-ignorenot xxx     add a pattern to the ignorenot list
-nocreation xxx    prevent file creations on one replica
-nodeletion xxx    prevent file deletions on one replica
-noupdate xxx      prevent file updates and deletions on one replica
-owner             synchronize owner
-path xxx          path to synchronize
-perms n           part of the permissions which is synchronized
-root xxx          root of a replica (should be used exactly twice)
-silent            print nothing except error messages
-terse             suppress status messages
-testserver        exit immediately after the connection to the server
-times             synchronize modification times
-version           print version and exit

Advanced options:
-addprefsto xxx    file to add new prefs to
-addversionno      add version number to name of unison on server
-backup xxx        add a pattern to the backup list
-backupcurr xxx    add a pattern to the backupcurr list
-backupcurrnot xxx add a pattern to the backupcurrnot list
-backupdir xxx     directory for storing centralized backups
-backuploc xxx     where backups are stored ('local' or 'central')
-backupnot xxx     add a pattern to the backupnot list
-backupprefix xxx  prefix for the names of backup files
-backups           keep backup copies of all files (see also 'backup')
-backupsuffix xxx  a suffix to be added to names of backup files
-confirmbigdel     ask about whole-replica (or path) deletes (default true)
-confirmmerge      ask for confirmation before commiting results of a merge
-contactquietly    suppress the 'contacting server' message during startup
-copymax n         maximum number of simultaneous copyprog transfers
-copyprog xxx      external program for copying large files
-copyprogrest xxx  variant of copyprog for resuming partial transfers
-copyquoterem xxx  add quotes to remote file name for copyprog (true/false/default)
-copythreshold n   use copyprog on files bigger than this (if >=0, in Kb)
-debug xxx         debug module xxx ('all' -> everything, 'verbose' -> more)
-diff xxx          set command for showing differences between files
-dontchmod         when set, never use the chmod system call
-dumbtty           do not change terminal settings in text UI
-fastcheck xxx     do fast update detection (true/false/default)
-follow xxx        add a pattern to the follow list
-force xxx         force changes from this replica to the other
-forcepartial xxx  add a pattern to the forcepartial list
-halfduplex        force half-duplex communication with the server
-height n          height (in lines) of main window in graphical interface
-host xxx          bind the socket to this host name in server socket mode
-ignorearchives    ignore existing archive files
-ignorecase xxx    identify upper/lowercase filenames (true/false/default)
-ignoreinodenumbers ignore inode number changes when detecting updates
-ignorelocks       ignore locks left over from previous run (dangerous!)
-immutable xxx     add a pattern to the immutable list
-immutablenot xxx  add a pattern to the immutablenot list
-key xxx           define a keyboard shortcut for this profile (in some UIs)
-killserver        kill server when done (even when using sockets)
-label xxx         provide a descriptive string label for this profile
-links xxx         allow the synchronization of symbolic links (true/false/default)
-log               record actions in logfile (default true)
-logfile xxx       logfile name
-maxbackups n      number of backed up versions of a file
-maxerrors n       maximum number of errors before a directory transfer is aborted
-maxthreads n      maximum number of simultaneous file transfers
-merge xxx         add a pattern to the merge list
-mountpoint xxx    abort if this path does not exist
-nocreationpartial xxx add a pattern to the nocreationpartial list
-nodeletionpartial xxx add a pattern to the nodeletionpartial list
-noupdatepartial xxx add a pattern to the noupdatepartial list
-numericids        don't map uid/gid values by user/group names
-prefer xxx        choose this replica's version for conflicting changes
-preferpartial xxx add a pattern to the preferpartial list
-repeat xxx        synchronize repeatedly (text interface only)
-retry n           re-try failed synchronizations N times (text ui only)
-rootalias xxx     register alias for canonical root names
-rsrc xxx          synchronize resource forks (true/false/default)
-rsync             activate the rsync transfer mode (default true)
-selftest          run internal tests and exit
-servercmd xxx     name of unison executable on remote server
-showarchive       show 'true names' (for rootalias) of roots and archive
-socket xxx        act as a server on a socket
-sortbysize        list changed files by size, not name
-sortfirst xxx     add a pattern to the sortfirst list
-sortlast xxx      add a pattern to the sortlast list
-sortnewfirst      list new before changed files
-sshargs xxx       other arguments (if any) for remote shell command
-sshcmd xxx        path to the ssh executable
-stream            use a streaming protocol for transferring file contents (default true)
-ui xxx            select UI ('text' or 'graphic'); command-line only
-unicode xxx       assume Unicode encoding in case insensitive mode
-xferbycopying     optimize transfers using local copies (default true)

Configuration et tests

La configuration des répertoires et données à synchroniser doit se faire dans un répertoire situé sur le home de l'utilisateur : ~/.unison/, à créer manuellement. Ce répertoire peut contenir un ou plusieurs fichiers de configuration ("profil") qui se présentent sous cette forme :
$ cat ~/.unison/paper.prf
times = true
owner = true
group = true

root = /home/kbux/
root = ssh://kbux@ktux1//home/kbux/
path = ./paper/

logfile = /home/kbux/.unison/paper.log
Respectivement, nous avons :
  • times : synchroniser les dates de modification
  • owner : synchroniser le propriétaire des données
  • group : synchroniser les permissions pour le group
  • root (première instance) : répertoire source (avec un cran au dessus par rapport au répertoire contenant les données que nous voulons répliquer)
  • root (seconde instance) : répertoire de destination, les 2 instances pouvant adresser soit en ssh, soit en local soit à travers des sockets
  • path : chemin relatif où sont stockées nos données à répliquer, à partir du répertoire mentionné à la première instance de root
  • logfile : fichier journal
Bien entendu, il est possible d'enrichir encore plus le profil, mais comme le but de ce tip est avant tout démonstratif, nous en resterons là niveau conf. Lorsque l'on invoque unison, il ne faut pas spécifier le fichier de configuration en lui-même mais juste le nom du profil, sans extension. La recherche du profil se fera exclusivement dans ~/.unison.

Premier lancement

Du coup, si on lance unison sur un profil pareil, nous aurons :
$ unison paper
Contacting server...
Connected [//ktux0//home/kbux/ -> //ktux1//home/kbux/]
Looking for changes
Warning: No archive files were found for these roots, whose canonical names are:
/home/kbux/
//ktux1//home/kbux
This can happen either
because this is the first time you have synchronized these roots,
or because you have upgraded Unison to a new version with a different
archive format.

Update detection may take a while on this run if the replicas are
large.

Unison will assume that the 'last synchronized state' of both replicas
was completely empty.  This means that any files that are different
will be reported as conflicts, and any files that exist only on one
replica will be judged as new and propagated to the other replica.
If the two replicas are identical, then no changes will be reported.

If you see this message repeatedly, it may be because one of your machines
is getting its address from DHCP, which is causing its host name to change
between synchronizations.  See the documentation for the UNISONLOCALHOSTNAME
environment variable for advice on how to correct this.

Donations to the Unison project are gratefully accepted:
http://www.cis.upenn.edu/~bcpierce/unison

Press return to continue.[<spc>]    Waiting for changes from server
Reconciling changes

local          ktux1
file     ---->            paper/paper0  [f]
file     ---->            paper/paper1  [f]
file     ---->            paper/paper2  [f]
file     ---->            paper/paper3  [f]

Proceed with propagating updates? [] y
Propagating updates

UNISON 2.40.61 started propagating changes at 12:05:29.60 on 15 Mar 2011
[BGN] Copying paper/paper0 from /home/kbux to //ktux1//home/kbux
[BGN] Copying paper/paper1 from /home/kbux to //ktux1//home/kbux
[BGN] Copying paper/paper2 from /home/kbux to //ktux1//home/kbux
[BGN] Copying paper/paper3 from /home/kbux to //ktux1//home/kbux
Shortcut: copied /home/kbux/paper/paper3 from local file /home/kbux/paper/.unison.paper2.d2917910e40aeb61dcb98658569b3b8c.unison.tmp
Shortcut: copied /home/kbux/paper/paper2 from local file /home/kbux/paper/.unison.paper1.d2917910e40aeb61dcb98658569b3b8c.unison.tmp
Shortcut: copied /home/kbux/paper/paper1 from local file /home/kbux/paper/.unison.paper0.d2917910e40aeb61dcb98658569b3b8c.unison.tmp
[END] Copying paper/paper3
[END] Copying paper/paper2
[END] Copying paper/paper1
[END] Copying paper/paper0
UNISON 2.40.61 finished propagating changes at 12:05:29.60 on 15 Mar 2011

Saving synchronizer state
Synchronization complete at 12:05:29  (4 items transferred, 0 skipped, 0 failed)
ktux1 $ ll /home/kbux/paper/
total 8
drwxr-xr-x  2 kbux kbux 4096 2011-03-15 12:05 .
drwxrwxrwt 38 root      root   4096 2011-03-15 12:01 ..
-rw-r--r--       1 kbux kbux    0 2011-03-15 11:59 paper0
-rw-r--r--       1 kbux kbux    0 2011-03-15 11:59 paper1
-rw-r--r--       1 kbux kbux    0 2011-03-15 11:59 paper2
-rw-r--r--       1 kbux kbux    0 2011-03-15 11:59 paper3
Au second lancement, si rien ne bouge :
$ unison paper
Contacting server...
Connected [//ktux0//home/kbux -> //ktux1//home/kbux]
Looking for changes
Waiting for changes from server
Reconciling changes
Nothing to do: replicas have not changed since last sync.

Modifications de données sur l'un des réplicas

Suppression

Si l'on supprime le contenu de notre /home/kbux/paper/ sur la machine de destination ktux1, par défaut et sans stipuler l'inverse, nous allons directement à la réplication des données modifiées sur celles antérieures : donc suppression pure et simple du contenu de /home/kbux/paper/ sur ktux0. Pour information, on peut -et heureusement- spécifier la décision à l'énumération de chaque donnée modifiée, en lieu et place du [f].
$ unison paper
Contacting server...
Connected [//ktux0//home/kbux -> //ktux1//home/kbux]
Looking for changes
Waiting for changes from server
Reconciling changes
The following paths have been completely emptied in one replica:
'paper'
Unison may delete everything below these paths in the other replica.

(Set the 'confirmbigdel' preference to false to disable this check.)

Do you really want to proceed? [] y
local          ktux1
<---- deleted    paper/paper0  [f]
<---- deleted    paper/paper1  [f]
<---- deleted    paper/paper2  [f]
<---- deleted    paper/paper3  [f]

Proceed with propagating updates? [] y
Propagating updates

UNISON 2.40.61 started propagating changes at 12:13:20.04 on 15 Mar 2011
[BGN] Deleting paper/paper0 from /home/kbux
[BGN] Deleting paper/paper1 from /home/kbux
[BGN] Deleting paper/paper2 from /home/kbux
[BGN] Deleting paper/paper3 from /home/kbux
[END] Deleting paper/paper0
[END] Deleting paper/paper1
[END] Deleting paper/paper2
[END] Deleting paper/paper3
UNISON 2.40.61 finished propagating changes at 12:13:20.04 on 15 Mar 2011

Saving synchronizer state
Synchronization complete at 12:13:20  (4 items transferred, 0 skipped, 0 failed)

Rajout

Reprenons avec notre /home/kbux/paper plein sur ktux0 (la source) et après avoir lancé notre mirroring sur ktux1 (la destination). Nous avons donc ktux0:/home/kbux/paper strictement égal à ktux1:/home/kbux/paper. On crée un fchier sur ktux1 : /home/kbux/paper/paper4.
ktux1 $ touch /home/kbux/paper/paper4
ktux0 $ unison paper
Contacting server...
Connected [//ktux0//home/kbux -> //ktux1//home/kbux]
Looking for changes
Waiting for changes from server
Reconciling changes

local          ktux1
<---- new file   paper/paper4  [f]

Proceed with propagating updates? [] y
Propagating updates

UNISON 2.40.61 started propagating changes at 12:17:15.79 on 15 Mar 2011
[BGN] Copying paper/paper4 from //ktux1//home/kbux to /home/kbux
Shortcut: copied /home/kbux/paper/paper4 from local file /home/kbux/paper/paper3
[END] Copying paper/paper4
UNISON 2.40.61 finished propagating changes at 12:17:15.80 on 15 Mar 2011

Saving synchronizer state
Synchronization complete at 12:17:15  (1 item transferred, 0 skipped, 0 failed)
Et donc, sur ktux0, qui n'avait jusque là pas eu de paper4 sur /home/kbux/paper :
$ ll /home/kbux/paper/paper4
-rw-r--r-- 1 kbux kbux 0 2011-03-15 12:17 /home/kbux/paper/paper4
Si on tend un peu l'oreille, on s'aperçoit qu'il s'agit en réalité d'utiliser ssh pour ce cas-ci. Il existe 3 manières d'ouvrir une connexion : local, SSH et socket. Du coup, rien n'empêche d'adresser, au hasard, un montage en CIFS (plus connu sous le nom de SMB).

Modification

Lors de mise à jour des données, mieux vaut ne pas se tromper, car cela risque de laisser des souvenirs déplaisants. Si l'on veut bien se rendre compte de ce que l'on est sur le point de transférer, on peut utiliser l'option diff pour déjà donner la commande qui nous servira à montrer les différences entre les réplicas. Meilleure visibilité donc meilleure anticipation sur les choix à faire. Au passage, un petit tour sur l'aide qui permet notamment de spécifier le sens de réplication (qui vers qui).
$ unison paper -diff diff
Contacting server...
Connected [//ktux0//home/kbux -> //ktux1//home/kbux]
Looking for changes
Waiting for changes from server
Reconciling changes

local          ktux1
<---- changed    paper/paper0  [f] ?
Commands:
<ret> or f or <spc>   follow unison's recommendation (if any)
I                     ignore this path permanently
E                     permanently ignore files with this extension
N                     permanently ignore paths ending with this name
m                     merge the versions
d                     show differences
x                     show details
L                     list all suggested changes tersely
l                     list all suggested changes with details
p or b                go back to previous item
g                     proceed immediately to propagating changes
q                     exit unison without propagating any changes
/                     skip
> or .                propagate from from local to ktux1
< or ,                propagate from from ktux1 to local
<---- changed    paper/paper0  [f] d

diff '/home/kbux/paper/paper0' '/home/kbux/paper/paper0.unison.diff-'

0a1
> paper0
Comme je vous l'ai dit un peu plus haut, il est possible également de stipuler dans quel sens les modifications sont à faire, par exemple en interactive, en précisant > (src to dest) ou < (dest to src).

Conclusion

Je ne vous cache pas que cet outil peut être très très dangereux, surtout en fin de journée et/ou en fin de semaine chargée. Néanmoins, il permet d'avoir exactement les mêmes données sur plusieurs emplacements différents et, accommodé de bons points de montage, il permet de faire sûrement et rapidement un backup de données. C'est d'autant plus facile qu'il est possible de le scripter, quoiqu'un contrôle visuel et interactif est tout de même plus rassurant.
Vus : 4350
Publié par K-Tux : 59