Correctement renommer un fichier de configuration dans un paquet Debian

Après avoir traité de la suppression de conffiles obsolètes, je vais maintenant aborder la question du renommage des fichiers de configuration gérés par dpkg.

La problématique

Prenons pour hypothèse que la version 1.2 d’une quelconque application ne fournisse plus le fichier /etc/foo.conf. En lieu et place, elle fournit /etc/bar.conf, car le fichier de configuration a été renommé. Si vous ne faîtes rien de particulier, le nouveau conffile sera installé et contiendra la configuration par défaut, tandis que l’ancien restera. Toutes les modifications éventuellement réalisées par l’administrateur seront perdues (inutilisées, pour être exact : elles seront toujours consignées dans le fichier foo.conf, qui ne sera plus pris en compte).

Bien entendu, il vous est toujours possible de procéder à un mv /etc/foo.conf /etc/bar.conf dans le script de pré-installation. Mais ce n’est pas satisfaisant : une questions sera posée à l’utilisateur final lors de la mise à jour, dont il ne comprendra pas la raison.

La solution

Vous devez vérifier, dans le script de pré-installation, si l’ancien conffile a été modifié par l’administrateur. Si tel est le cas, vous souhaitez le garder de côté. Dans le cas contraire, vous pourrez le supprimer une fois la mise à jour réalisée, et, pour bien s’en rappeler, vous le renommez en /etc/foo.conf.dpkg-remove dans ce cas.

Vous supprimez ensuite /etc/foo.conf.dpkg-remove dans le script de post-installation. Si l’ancien conffile (/etc/foo.conf) existe toujours, c’est qu’il a été modifié par l’administrateur. Il ne reste plus alors qu’à faire une copie de sauvegarde du nouveau conffile vers /etc/bar.conf.dpkg-dist, et renommer l’ancien en /etc/bar.conf.

Dans le script postrm, dans le cas d’un appel pour annuler la mise à jour, le fichier /etc/foo.conf.dpkg-remove doit retrouver son nom originel.

En pratique, utilisez dpkg-maintscript-helper

dpkg-maintscript-helper permet d’automatiser toutes ces tâches. Vous n’avez qu’à ajouter l’extrait de code suivant dans chaque script (postinst, postrm, preinst) :

if dpkg-maintscript-helper supports mv_conffile 2>/dev/null; then
    dpkg-maintscript-helper mv_conffile /etc/foo.conf /etc/bar.conf 1.1-3 -- "$@"
fi

J’ai considéré dans cet exemple que la dernière version du paquet contenant /etc/foo.conf (i.e. la dernière version avant la parution de la 1.2-1) était la 1.1-3.

Vous pouvez faire l’économie des tests préliminaires en imposant une pré-dépendance à « dpkg (>= 1.15.7.2) », ou si suffisamment de temps s’est écoulé pour considérer comme probable que tout le monde dispose d’une version plus récente. Vous trouverez tous les détails sur ce point dans la page de manuel de dpkg-maintscript-helper.

Cet article est une traduction de Correctly renaming a conffile in Debian package maintainer scripts contribuée par Weierstrass01. Suivez moi sur Identi.ca, Twitter et Facebook. Ou abonnez-vous à ce blog par RSS ou par email.

La bonne manière de supprimer un fichier de configuration obsolète dans un paquet Debian

Un conffile est un fichier de configuration géré par dpkg, mais je suis certain que vous vous souvenez de cet article introductif à propos des conffiles. Lorsque votre paquet cesse de fournir un conffile, celui-ci reste simplement sur le disque et est considéré comme « obsolète » par le gestionnaire de paquets. Il n’est retiré que dans le cas de la purge (et non de la simple suppression) du paquet. Si vous souhaitez que ce fichier soit retiré avant ce terme, il ne vous reste plus qu’à coder vous-même en ce sens les scripts de configuration de vos paquets. Voyons donc comment.

Quand est-ce nécessaire ?

dpkg privilégie la sécurité en ne supprimant pas ce fichier sauf en cas de purge. Pourtant, il est généralement plus avisé de le faire plus tôt pour ne pas induire l’utilisateur en erreur. C’est même obligatoire dans certains cas, puisque garder le conffile pourrait provoquer des erreurs logicielles (par exemple dans le cas où il se trouve dans un dossier « .d », et qu’il contient des entrées plus supportées ou contradictoires avec celles de nouveaux conffiles).

Qu’est-ce que « rm » a donc de compliqué ?

Vous souhaitez donc supprimer le conffile. Ajouter une commande « rm » dans debian/postinst semble plutôt facile. Certes, mais ce n’est pas du tout la bonne manière de procéder ! Il se pourrait que le conffile contienne certaines adaptations faites par l’administrateur, que vous ne souhaitez pas perdre. Plutôt que de supprimer, vous souhaitez plutôt garder le fichier dans un coin, afin que l’administrateur puisse récupérer ce qu’il avait fait et s’en servir comme bon lui semble.

La bonne action à prendre est donc de demander le déplacement de ce fichier dans le script prerm, afin d’éviter toute interférence avec la nouvelle version. Simultanément, vous devez vérifier si le conffile a été modifié par l’utilisateur, et, si c’est le cas, le retenir pour plus tard. Puis, dans le script postinst, le supprimer s’il n’y aucun changement entre la nouvelle et l’ancienne version, ou le garder sous un autre nom, si différence il y a. Ajouter un suffixe type .dpkg-bak est généralement suffisant, dans la mesure où de nombreuses applications sont configurées pour ne prendre en compte que les fichiers d’une certaine extension (*.conf, au hasard). run-parts, par exemple, ignore tous les fichiers contenant un point dans leurs noms. Dans le script postrm enfin, il est nécessaire de supprimer les conffiles conservés jusque-là en raison de changements locaux et, au cas où l’installation rendant obsolète le conffile est annulée, restaurer l’ancienne version.

Automatisons tout cela grâce à dpkg-maintscript-helper

Fioouuuu… c’est une longue liste de tâches à réaliser pour une action apparemment simple ! Heureusement, tout cela peut être automatisé grâce à dpkg-maintscript-helper. Partons du principe que vous souhaitez supprimer /etc/foo/conf.d/bar, du fait qu’il est maintenant dépassé et que vous préparez une nouvelle version 1.2-1 qui le supprimera lors de la mise à jour. Il vous suffit de copier-coller l’extrait de code suivant dans les 3 scripts (preinst, postinst, postrm) :

if dpkg-maintscript-helper supports rm_conffile 2>/dev/null; then
    dpkg-maintscript-helper rm_conffile /etc/foo/conf.d/bar 1.2-1 -- "$@"
fi

Le if peut être évité en posant une dépendance à « dpkg (>= 1.15.7.2) », ou s’il s’est écoulé suffisamment de temps pour supposer que tout le monde dispose d’une version assez récente. La page de manuel de dpkg-maintscript-helper vous apportera tous les détails nécessaires.

Cet article est une traduction de The right way to remove an obsolete conffile in a Debian package contribuée par Weierstrass01. Abonnez-vous à ce blog par RSS ou par email pour recevoir tous les prochains articles et améliorer votre maîtrise de Debian/Ubuntu.