Garder l'historique des changements de /etc
grâce aux outils de suivi de version (svn, svk)

Version 1.1, ($Revision: 21 $, $Date: 2009-03-22T20:05:08.031398Z $).

Guillaume Allègre

La version initiale de ce tutoriel est paru dans le numéro 115 (avril 2009) de GNU/Linux Magazine France.
Ce tutoriel s'adresse aux administrateurs système, qui ont l'habitude de modifier les nombreux fichiers de configuration du répertoire /etc. Un outil de suivi de versions (versionning) peut énormément leur simplifier la tâche, surtout s'il s'agit de mémoriser les versions successives, en se réservant la possibilité de revenir en arrière. Malheureusement, ce type d'outils bien connu des développeurs ne fait souvent pas partie de la culture de base des administrateurs système, mais nous allons essayer de corriger cette lacune !

Nous allons voir dans cet article comment nous y prendre, avec deux outils assez proches, subversion (svn) et svk. Ces deux commandes ont des larges possibilités conçues pour gérer des "projets logiciels" complets, mais nous nous contenterons dans cet article d'un nombre limité de fonctionnalités, en négligeant celles qui servent essentiellement aux développeurs travaillant en équipe (multi-utilisateurs, synchronisation sur un serveur réseau). Toutefois, j'espère que les exemples vous mettront le pied à l'étrier pour découvrir par vous-mêmes les autres fonctionnalités de svn/svk.

SVN ou SVK ?

Il existe actuellement de nombreux systèmes de gestion de versions (en anglais, SCM, Source Code Management, ou VCS, Version Control System), dont le plus populaire est encore subversion (svn), même s'il est fonctionnellement dépassé par des avatars plus modernes, comme git, mercurial ou bazaar.

SVN reste conceptuellement assez simple ; si vous ne connaissez aucun VCS, vous pouvez commencer par celui-ci. SVK est une sur-couche à SVN, implémentée en Perl, qui lui apporte quelques fonctionnalités intéressantes. Dans le cas qui nous occupe, svk est aussi simple à utiliser que svn (voire même un peu plus à l'initialisation), avec un effet de bord intéressant, comme nous allons le voir.

Le préalable est donc d'installer subversion, et éventuellement svk. Vous pouvez très certainement le faire avec votre outil favori de gestion de paquets, aptitude, yum ou toute surcouche graphique. Je donnerai ensuite quelques astuces qui sont plus typiquement réservées à Debian et dérivées, mais l'essentiel de l'article s'applique à toutes les distributions.

En résumé : SVN est plus standard mais SVK est plus adapté à notre besoin.

Passer /etc sous Subversion

Notre but est donc de "versionner" toute la hiérarchie /etc afin de pouvoir par la suite interroger l'évolution de nos fichiers de configuration. Le principe avec subversion est simple : le répertoire /etc va devenir une copie de travail (working copy) d'un "projet" (un répertoire en fait) que nous allons baptiser etc-svn et qui sera stocké dans un dépôt (repository) séparé. Dans une utilisation classique, chaque développeur a sa propre copie de travail sur sa machine, et le dépôt est assuré par un serveur accessible via un protocole réseau. Pour nous, deux particularités : le dépôt est local, et ne sera ouvert qu'au seul utilisateur root.

La première étape est de créer l'espace du dépôt. Nous effectuons ici une configuration système, donc l'utilisation du compte root est inévitable :

# mkdir /var/lib/svndepots # svnadmin create /var/lib/svndepots/etc-svn

La première commande (mkdir) est juste là pour créer un répertoire destiné aux multiples dépôts SVN que vous voudrez gérer sur le système. Vous pouvez aussi décider de le garder sous /root si vous préférez. La deuxième ligne est spécifique à la création d'un dépôt SVN. Vous donnez un chemin complet, dont le dernier composant (etc-svn) est créé par la commande. Automatiquement, le répertoire est peuplé :

# ls /var/lib/svndepots/etc-svn/ conf db format hooks locks README.txt

Vous pouvez explorer ce répertoire, mais le contenu est quelque peu cryptique. Pour l'instant, vous avez tout à fait le droit de le considérer comme une boîte noire. Les commandes svnadmin et svn vous permettront plus tard d'en retirer les informations intéressantes.

Les commandes svnadmin et svn sont structurées de la même manière : elles sont suivies d'une sous-commande, éventuellement d'options, et d'arguments. svnadmin help vous fournit la liste des commandes ; svnadmin help sscmd détaille une sous-commande. Idem pour la commande svn.

Nous allons maintenant initialiser le dépôt proprement dit, à partir du contenu de /etc :

# cd /etc # svn import . file:///var/lib/svndepots/etc-svn/ -m "import initial"

Nous obtenons un défilé de lignes "Ajout nom_de_fichier", suivi de "Révision 1 propagée." On peut remarquer que l'option -m introduit un message manuel (commentaire) résumant la modification (ici, l'import initial). Si vous l'omettez, la commande appellera l'éditeur interactif (défini par la variable d'environnement EDITOR) pour que vous puissiez entrer ce message. La révision correspondante est numérotée 1. Ce numéro s'incrémentera régulièrement et automatiquement avec les modifications successives. Le premier argument (.) est le chemin du contenu à importer. C'est bien un chemin, relatif ou absolu. Le deuxième argument est l'URL du dépôt. Ici, le dépôt est local, donc l'URL est préfixée par le protocole file:// ; les autres protocoles autorisés par SVN sont : svn, svn+ssh, http(s). De façon générale, SVN distingue toujours chemin et URL, même s'il sait travailler tantôt sur une forme tantôt sur l'autre.

Le travail n'est pas fini pour autant : le dépôt est créé, mais /etc n'est pas encore une copie de travail de celui-ci. Voici donc le passage le plus délicat. Pour facilement pouvoir revenir en arrière, on va transformer /etc en lien symbolique sur une une copie de sauvegarde :

# cd / # mv /etc /etc-orig && ln -s /etc-orig /etc # svn checkout file:///var/lib/svndepots/etc-svn # ln -sf /etc-svn /etc

Encore un défilé de lignes "A /etc-svn/nom_de_fichier", terminé par "Révision 1 extraite." Ceci fait, vous pouvez vérifier que tout s'est bien passé avec la commande :

# cd /etc && svn info Chemin : . URL : file:///var/lib/svndepots/etc-svn ...

Voilà, vous avez votre copie de travail ! Cette séquence n'est pas particulièrement critique, et on a utilisé un lien symbolique pour basculer en un temps le plus court possible de /etc-orig vers /etc-svn. Si quelque chose tourne mal, rétablissez juste le lien symbolique vers /etc-orig. Il n'est pas inutile non plus de garder une sauvegarde (tar...) du répertoire /etc. Le mieux est quand même de vous entraîner un peu avant de vous lancer sur un serveur en production. Les commandes svn import et svn checkout ne devraient maintenant plus vous servir ; elles sont limitées à l'initialisation du dépôt et de la copie de travail respectivement. De même, /etc-orig sera inutile dès que vous vous serez assuré que tout fonctionne bien avec l'arborescence versionnée.

Si maintenant vous regardez le contenu de votre nouveau /etc, vous allez constater qu'il a presque doublé de volume par rapport à l'original : cela est dû aux répertoires cachés .svn qui le parsèment. Ce sont les métadonnées de Subversion. Elles contiennent en particulier un cache du dépôt, pour accélérer les comparaisons quand le dépôt est accessible à travers un réseau. Ici, ce cache est inutile, puisque le dépôt est local, mais svn conserve son fonctionnement habituel. Le premier défaut de ce cache est donc le doublement de la taille du dépôt ; son deuxième défaut est la présence de ces répertoires .svn, qui dans des cas très rares peuvent légèrement perturber le système (messages d'avertissement par exemple). Toutefois, ces deux petits désagréments sont très largement contrebalancés par le confort que procure svn.

Passer /etc sous svk

svk est un système de gestion de versions décentralisé, c'est-à-dire qu'il vous permet de gérer votre propre dépôt personnel (un par utilisateur système), et éventuellement de le synchroniser périodiquement à un dépôt centralisé (collaboratif). Dans notre cas, le dépôt sera affecté à root et autonome.

Si vous n'avez aucun dépôt standard pour root, crééez-en un avec :

# svk depotmap --init Repository /root/.svk/local does not exist, create? (y/n) y

Vous avez maintenant un dépôt personnel pour root, qui sera référencé par svk sous le nom //local.

# cd /etc # svk import . //local/etc --to-checkout -m "import initial" Committed revision 1. Import path //local/etc initialized. Committed revision 2.

Ici, l'option --to-checkout permet d'effectuer à la fois l'import et l'extraction de la copie de travail ; par rapport à svn, elle nous fait donc gagner une étape. D'autre part, le répertoire /etc n'est en rien modifié en devenant copie de travail (pas de répertoires .svn).

Le seul inconvénient de svk sur svn est que les opérations suivantes demandent plus de ressources ; un update, immédiat avec svn, peut prendre quelques secondes avec svk sur une machine de faible puissance et avec un répertoire bien peuplé (comme l'est /etc généralement).

Utilisation de notre /etc versionné.

Je suppose maintenant que vous avez utilisé svk ; si vous avez préféré svn, aucune importance : les sous-commandes sont quasiment les mêmes. Je signalerai les rares divergences.

Commencez à prendre en main les possibilités de svn/svk avec une opération simple : modifiez le fichier /etc/passwd, par exemple pour changer le shell d'un utilisateur, puis tapez la commande suivante :

/etc# svk status M passwd

svk vous indique la liste des fichiers qui sont dans un état (status) différent de celui du dépôt, précédé par un code mnémotechnique : M=modifié. svk help status vous en dira plus sur les codes et états possibles. svk diff vous permet d'en savoir encore plus :

/etc# svk diff === passwd ================================================================== --- passwd (revision 17) +++ passwd (local) ... -allegre:x:1001:1001:Guillaume Allegre,,,:/home/allegre:/bin/bash +allegre:x:1001:1001:Guillaume Allegre,,,:/home/allegre:/bin/zsh ...

Si vous ne connaissez pas la commande diff, profitez-en pour vous familiariser avec elle et sa soeur patch ; tous les VCS reposent sur elles pour gérer les fichiers textuels. Ici, l'exemple est simple et ne devrait pas vous arrêter.

Vous pouvez continuer vos modifications sur /etc/passwd. Après quoi, deux solutions s'offrent à vous. La première est d'entériner vos changements, avec la sous-commande commit :

/etc# svk commit -m "utilisateur allegre sous zsh" Committed revision 3. /etc# svk status /etc#

Ainsi, vous mettez à jour le dépôt et votre copie de travail est maintenant synchronisée (svk status ne renvoie aucun changement). L'autre alternative est d'annuler vos changements (avant commit, donc) par :

/etc# svk revert passwd Reverted passwd /etc# svk status

De cette façon aussi la copie de travail est resynchronisée avec le dépôt. Maintenant, supposons qu'on ajoute un utilisateur par une commande standard :

/etc# adduser cecile Ajout de l'utilisateur « cecile »... ... /etc# svk status M group M gshadow M passwd M shadow /etc# svk commit -m "ajout utilisateur cecile" Committed revision 4. /etc#

La commande adduser a modifié 4 fichiers, ce dont svk status nous informe. On décide de commiter cette modification, avant d'en faire d'autres. On effectue ici un "commit atomique" : les 4 fichiers sont marqués comme modifiés ensemble, et sous un mémo commun. Si on choisit de revenir en arrière, les 4 fichiers resteront dans un état cohérent.

On peut maintenant consulter une synthèse des révisions successives du dépôt :

/etc# svk log ---------------------------------------------------------------------- r4: root | 2009-02-08 23:16:39 +0100 ajout utilisateur cecile ---------------------------------------------------------------------- r3: root | 2009-02-08 22:58:34 +0100 utilisateur allegre sous zsh ---------------------------------------------------------------------- r2: root | 2009-01-28 20:10:37 +0100 Initial import. ---------------------------------------------------------------------- r1: root | 2009-01-28 20:10:07 +0100 Directory for svk import. ----------------------------------------------------------------------

Deux options utiles sont -r révision (ou intervalle de révisions), et -v (verbose), qu'on peut combiner :

/etc# svk log -r4:3 -v ---------------------------------------------------------------------- r4: root | 2009-02-08 23:16:39 +0100 Changed paths: M /etc/group M /etc/gshadow M /etc/passwd M /etc/shadow ajout utilisateur cecile ---------------------------------------------------------------------- r3: root | 2009-02-08 22:58:34 +0100 Changed paths: M /etc/passwd utilisateur allegre sous zsh ----------------------------------------------------------------------

En particulier, -v donne tous les fichiers affectés lors d'un commit atomique. Inversement, l'affichage le plus compact est fourni par -q (quiet).

Lorsque vous avez terminé une séance de travail dans /etc, et également avant de commencer, il est logique d'effectuer un svk update. Cette opération est le symétrique du commit : elle met à jour votre copie de travail en fonction des changements qui ont eu lieu dans le dépôt (par d'autres). Dans notre cas, il ne devrait pas y en avoir, mais le faire permet de garder les bonnes habitudes de synchronisation dans les deux sens.

/etc# svk update Syncing //etc(/etc) in /etc to 4.

Maintenant, supposons que vous examiniez un fichier particulier et que vous vous demandiez "d'où sort cette ligne suspecte ?". Vous pouvez commencez par lister les modifications de ce fichier, en précisant son nom : par exemple svk log passwd. Si cela ne suffit pas, la sous-commande blame vous mettra sur la piste :

/etc# svk blame passwd Annotations for /etc/passwd (4 active revisions): **************** ... 3 ( root 2009-02-08): foobar:x:1002:1002:foobar utilisateur test,,,:/home/foobar:/bin/zsh ...

Chaque ligne du fichier cible est affichée précédée de trois informations : la révision de modification, l'auteur (pas intéressant ici) et la date. Vous pouvez alors coupler cette interrogation avec un svn log ciblé pour en savoir plus sur le contexte de la modification (heure, mémo, autres fichiers impactés...).

Si maintenant vous décidez d'annuler une modification, concentrez-vous : c'est la partie la plus compliquée, même si elle n'a rien d'insurmontable. Tout d'abord, souvenez-vous qu'une modification commitée sera toujours présente dans l'historique : si la révision 4 ne convient pas, modifiez le nécessaire et passez à la révision 5. C'est le principe de base d'un gestionnaire de version.

Il existe généralement plusieurs manières de faire, la plus rudimentaire étant de défaire à la main (édition du fichier) ce que vous avez fait précédemment, puis de commiter. Hop, c'est réglé. Mais si vous voulez revenir sur un commit isolé bien identifié, il y a plus direct. Supposons que vous vouliez annuler l'ajout de l'utilisateur cecile :

/etc# svk merge -c -4 //etc U gshadow U shadow U group U passwd /etc# svk status M group M gshadow M passwd M shadow /etc# svk commit -m "annulation utilisateur cecile" Committed revision 5. /etc# svk up Syncing //etc(/etc) in /etc to 5.

La sous-commande merge est la combinaison d'un svk diff avec un patch. Elle n'affecte que la copie de travail, dont elle met à jour (U=update) les fichiers. Dans toute sa généralité, l'emploi de merge est assez compliqué. Ici, nous appliquons le commit de la révision 4 à l'envers (pour l'annuler), ce qui se note -c -4. Mais svk help merge (et la doc de référence) vous en diront plus sur le sujet.

Enfin, vous pouvez appliquer un commit à un nombre limité de fichiers, si vous les précisez sur la ligne de commande. Par exemple, on aurait pu faire (à tort) :

/etc# adduser cecile Ajout de l'utilisateur « cecile »... ... /etc# svk status M group M gshadow M passwd M shadow /etc# svk commit -m "ajout utilisateur cecile" passwd shadow Committed revision 4. /etc# svk commit -m "ajout groupe cecile" group gshadow Committed revision 5. /etc#

La règle générale est simple : respectez la logique des commits atomiques. Autrement dit, commitez ensemble les fichiers qui sont modifiés ensemble. Les deux écueils sont les commits trop gros (des changements qui n'ont rien à voir sont commités ensemble) et trop petits (4 fichiers liés sont commités séparément). La deuxième situation est gênante, mais moins que la première, qui pose un vrai problème si l'on veut annuler un changement. Moralité, dans le doute, mieux vaut découper trop fin que trop gros.

Impact sur la gestion des paquets (deb/rpm)

L'un des avantages de versionner /etc est la "surveillance" des installations de nouveaux logiciels par les paquets fournis par votre distribution. En effet, vous pouvez facilement connaître la liste des principaux fichiers installés (binaires, doc, pages de man...) avec dpkg -L ou rpm -ql, mais souvent les fichiers de configuration sont créés par des scripts de post-installation et ne sont pas listés par ces outils.

L'installation d'un paquet (et de ses dépendances éventuelles) peut avoir plusieurs actions sur les fichiers de configuration : une modification de fichiers existants, un ajout de nouveaux fichiers, et (plus rarement) une suppression. La commande svk status (abrégée en st) vous signalera la liste des fichiers affectés, préfixés par les caractères M, ? et ! respectivement. Supposons par exemple que nous souhaitions installer les (excellents) utilitaires du paquet sysstat :

/etc# svk st /etc# aptitude install sysstat ... OK ... /etc# svk st ? cron.d/sysstat ? cron.daily/sysstat ? default/sysstat ? init.d/sysstat M runlevel.conf ? sysstat /etc# svk add cron.d/sysstat cron.daily/sysstat default/sysstat init.d/sysstat sysstat A cron.d/sysstat A cron.daily/sysstat A default/sysstat A init.d/sysstat A sysstat A sysstat/sysstat A sysstat/sysstat.ioconf /etc# svk commit -m "install sysstat" Committed revision 12.

Après l'installation, svk status nous permet de voir que le paquet a modifié le fichier runlevel.conf, en a ajouté 4 autres, ainsi qu'un répertoire (sysstat), et ses sous-répertoire. Pour l'instant, ces ajouts sont inconnus du dépôt, et si nous faisons un commit, seul runlevel.conf sera pris en compte. Il faut signaler explicitement à svk quels sont les fichiers que nous voulons ajouter au dépôt. C'est le rôle de la commande svk add. Si les fichiers à ajouter sont vraiment trop nombreux, vous pouvez utiliser la syntaxte svk add --interactive *. Svk récupérera alors tous les fichiers qui lui sont inconnus, mais il vous demandera une confirmation individuelle (option --interactive), préférable quand vous utilisez un joker. Au passage, svk diff nous permettrait de connaître la modification apportée au fichier runlevel.conf avant de la commiter.

Si d'aventure un fichier (par exemple foobar) est supprimé par le script d'installation, c'est à peine plus compliqué. Comme dans le cas d'un ajout, il faut donc forcer la modification dans le dépôt. On y parvient par la séquence revert / del / commit :

# svk status ! foobar # svk revert foobar Reverted foobar # svk del foobar D foobar # svk commit -m "suppression propre de foobar" foobar

Mais évidemment si la suppression de foobar est liée à d'autres changements (ajouts, modifications), le commit final doit être commun.

Les règles générales lors de l'installation de paquets :

- synchronisez /etc au dépôt avant d'installer quoi que ce soit, pour ne pas mélanger les modifications en attente avec celles issues de l'installation

- re-synchronisez dès que vos paquets sont installés, avant d'avoir modifié les paramètres par défaut, avec un message de type "install tels-paquets"

- si vous effectuez des réglages dans les fichiers de configuration, commitez-les séparément, avec un message de type "configuration tel-paquet".

Ainsi, vous enregistrez séparément les réglages par défaut de la distribution et vos personnalisations. Cela vous fera gagner du temps si vous devez refaire les mêmes opérations sur une autre machine par exemple.

Astuces et recettes

Abandonner sysv-init au profit de file-rc (Debian)

Le but de cette manipulation est de limiter les manipulations nécessaires lors de l'installation d'un nouveau service dans /etc/init.d/*. Le système classique SysV-init, à base de liens symboliques est relativement simple et efficace mais a l'inconvénient de générer beaucoup de manipulation de fichiers lors de l'installation d'un service, qu'il faut reporter ensuite dans le dépôt par des manipulations svk.

L'administrateur se simplifie considérablement la vie en adoptant le système file-rc, qui remplace tous les répertoires rc?.d par le seul fichier /etc/runlevel.conf. Les scripts /etc/init.d/* ne changent pas, mais le mécanisme d'appel est modifié. Sous Debian, le changement se fait simplement en installant le paquet file-rc. Les personnalisation qui ont été faites sont prises en compte, et le mécanisme est parfaitement réversible : les paquets file-rc et sysv-rc sont marqués en conflit, et l'un est désinstallé quand l'autre s'installe. Avec file-rc, l'ajout d'un service se traduit par l'ajout d'une ou plusieurs lignes dans /etc/runlevel.conf, ce qui est bien plus confortable.

Rapatrier sous /etc des fichiers extérieurs

Dans certains cas, la distribution gère quelques fichiers de configuration extérieurs à /etc, par exemble pour Debian, les fichiers de configuration de GRUB, device.map et menu.lst sont stockés dans /boot/grub. Par souci d'exhaustivité, vous pouvez désirer les intégrer au versionnage d'etc. C'est faisable simplement grâce aux liens symboliques :

/# cd /etc /etc# mkdir grub /etc# cd /boot/grub/ /boot/grub# mv device.map menu.lst /etc/grub/ /boot/grub# ln -s /etc/grub/* . /boot/grub# cd /etc/ /etc# svk status ? grub /etc# svk add grub/ A grub A grub/device.map A grub/menu.lst /etc# svk commit -m "passage conf GRUB sous /etc" grub/ Committed revision 61.

Dans le cas (de plus en plus rare) où /boot est monté sur une partition extérieure à la racine, cette manipulation pourrait avoir des effets secondaires fâcheux. Prenez vos précautions.

Supprimer du dépôt des fichiers qui changent "sans raison"

Pour différentes raisons, certains fichiers de /etc sont modifiés sans intervention manuelle de l'administrateur. On trouve fréquemment : mtab, adjtime, ld.so.cache ... Clairement, ces fichiers créés automatiquement seraient plutôt à leur place sous /var, mais pour des raisons historiques ils sont sous /etc, et il faut faire avec. En temps normal, cela ne nous dérange pas, mais avec svk status, ils se comportent comme des "faux positifs". Voici comment régler le problème :

/etc# svk del --keep-local adjtime ld.so.cache mtab -m "suppression du dépot des fichiers autogénérés" /etc# svk st ? adjtime ? ld.so.cache ? mtab /etc# svk ignore adjtime ld.so.cache mtab M . /etc# svk commit --non-recursive -m "svk ignore : fichiers autogénérés" . Committed revision 48.

La première étape supprime du dépôt les fichiers ciblés. L'option --keep-local est primordiale : sans elle, les fichiers sont également effacés localement. On pourrait s'arrêter là : les fichiers n'étant plus connus du dépôt, ils ne seraient jamais commités. Cependant, ils compliquent l'affichage et gênent la lisibilité des futurs svk status. La solution repose sur une fonctionnalité de svn et svk appelée "propriétés", que l'on peut associer à tout répertoire ou fichier du dépôt. Nous n'allons pas décrire ces propriétés en détail, mais nous en utilisons une spécifique, appelée svn:ignore (svk reprend les propriétés svn), qui permet à la commande svk d'ignorer certains fichiers (qui ne doivent pas être connus du dépôt). La propriété s'applique au répertoire père de l'objet à ignorer ; ici, à /etc entier, qui est déclaré dans le . (point terminal) du commit. L'option --non-recursive du commit indique à la commande de ne pas commiter les éventuelles modifications en attente dans le répertoire, mais uniquement les modifications du répertoire lui-même.

Vous pouvez aussi appliquer cette règle à group- gshadow- passwd- shadow- par exemple.

Comment savoir de quel paquet dépend tel fichier de configuration ?

Si vous avez bien suivi la convention 1 installation = 1 commit, la commande svk log vous fournira la réponse, par exemple :

hulotte:/etc# svk log apt/apt.conf.d/90debsums ---------------------------------------------------------------------- r24: root | 2009-02-16 14:45:04 +0100 install debsums ----------------------------------------------------------------------

Évidemment, si vous obtenez "import initial", c'est loupé : le paquet a été ajouté avant votre installation de svk. Il fait peut-être partie de l'installation de base de votre distribution. En tous cas, c'est la raison pour laquelle il vaut mieux passer /etc sous svk le plus tôt possible lors de l'installation de votre système.

Inversement, comment savoir quels fichiers de configuration ont été déposés par tel paquet ?

Par exemple, pour le paquet sudo. Si vous avez bien suivi la convention 1 installation = 1 commit :

/etc# svk log | grep -B 3 sudo ---------------------------------------------------------------------- r15: root | 2009-01-13 19:50:48 +0100 install sudo /etc# svk log -r15 -v ---------------------------------------------------------------------- r15: root | 2009-01-13 19:50:48 +0100 Changed paths: A /etc-svk/init.d/sudo A /etc-svk/pam.d/sudo M /etc-svk/runlevel.conf A /etc-svk/sudoers install sudo ----------------------------------------------------------------------

Ainsi, on obtient la liste : 3 fichiers ajoutés et un fichier modifié.

Peut-on automatiser les interactions apt-svk ?

En un mot, oui, en s'appuyant sur les directives apt.conf disponibles : DPkg::Pre-Invoke et DPkg::Post-Invoke. Reste à savoir si c'est toujours souhaitable. J'opte ici pour une approche relativement configurable. On pourrait certainement pousser plus loin l'automatisation, en se basant sur le même canevas.

La personnalisation repose sur un script shell, /usr/sbin/etcvers-install, un fichier de configuration minimaliste, /etc/default/etcversionning, et la configuration de APT décrite plus haut.

Dans le répertoire /etc/apt/apt.conf.d/, ajoutez un fichier, par exemple 01etcversionning, contenant les deux lignes :

DPkg::Pre-Invoke { "/usr/sbin/etcvers-install pre" ; }; DPkg::Post-Invoke { "/usr/sbin/etcvers-install post" ; };

Puis le fichier /etc/default/etcversionning :

# Value should be "interactive", "batch" or "none" EtcVersMode="interactive"

Et enfin le script /usr/sbin/etcvers-install lui-même :

#! /bin/bash source /etc/default/etcversionning cd /etc read PKGFILE PKGNAME=$(basename $PKGFILE .deb) case "$EtcVersMode" in none) #no automatic control exit 0 ;; batch) #control -> automatic commit case "$1" in pre) svk commit -m "sync /etc before install $PKGNAME" exit 0 ;; post) svk commit -m "install $PKGNAME" exit 0 ;; esac ;; interactive) # control -> suspend install if uncommited changes FTMP="/tmp/svkstatus" NB=$(svk status |tee $FTMP |wc -l) case "$1" in pre) if [ $NB -eq 0 ] ; then # 0 change echo "OK : 0 changes left in /etc => proceeding." else echo "error: $NB changes left in /etc => aborting install." echo "Please sync with repository, then redo : " cat $FTMP exit 1 fi ;; post) if [ $NB -eq 0 ] ; then # 0 change echo "OK : 0 changes in /etc during install." exit 0 else echo "warning: $NB changes in /etc during install." echo "Don't forget to sync with repository :" cat $FTMP exit 0 fi ;; esac ;; esac exit 0

La variable EtcVersMode, dans le fichier /etc/default/etcversionning, permet de régler le degré d'automatisation lors de l'installation de nouveaux paquets. Avec la valeur none, rien ne change.

La valeur batch établit un mode le plus automatique possible : avant chaque installation, un commit des changements pendants est fait, de même qu'après.

La valeur interactive est à mon avis préférable : avant une installation, le script vérifie s'il y a des changements pendants. Si c'est le cas, il bloque l'installation, et demande à l'administrateur de régler le problème avant de recommencer. Après l'installation, il vérifie également si des changements ont eu lieu, et dans ce cas affiche un mémo pour l'administrateur. L'idée est qu'une série de paquets ont pu être installés en même temps par le jeu des dépendances alors qu'ils n'ont qu'un rapport lointain. Dans ce cas, il vaut mieux laisser l'administrateur décider de la granularité des commits.

Voir également

Il existe deux paquets Debian qui sont très proches de ce que nous avons fait : etcinsvk, issu du projet DebianEdu, utilise la même technique (svk), mais dans un objectif d'automatisation totale. Il réduit donc fortement la marge de manoeuvre de l'administrateur lors de l'installation de nouveaux paquets.

D'un autre côté, le paquet etckeeper adopte une approche généraliste, et permet de versionner /etc, au choix avec git, bazaar ou mercurial, mais pas encore avec svk. Cela dit, dans tous les cas, si la commande change, la méthodologie générale reste la même.

Vous pouvez retrouver la version en ligne de cet article à l'adresse http://www.silecs.info/tutoriels. Vous êtes encouragé à y contribuer, par l'ajout d'astuces, de suggestions ou de corrections.