Provided by:
debconf-doc_1.5.23ubuntu2_all 
NOM
debconf - guide du développeur
DESCRIPTION
C’est un guide pour créer des paquets qui utilisent debconf.
Ce manuel suppose que vous connaissez bien debconf en tant
qu’utilisateur et que vous êtes familier avec les bases de la
construction des paquets Debian.
Ce manuel commence par expliquer les deux nouveaux fichiers ajoutés aux
paquets Debian qui utilisent debconf. Puis il explique comment le
protocole debconf fonctionne et vous indique les bibliothèques qui
permettent de communiquer avec le protocole. Il traite les autres
scripts d’administration où debconf est typiquement utilisé : les
scripts postinst et postrm. Ensuite, il passe à des sujets plus pointus
comme le partage des questionnaires debconf, le débogage, d’autres
techniques courantes et les pièges de la programmation avec debconf. Il
se termine par une discussion sur les défauts actuels de debconf.
LE SCRIPT DE CONFIGURATION
Debconf ajoute un script d’administration, le script config, au jeu de
scripts pouvant être présents dans un paquet Debian (les scripts
postinst, preinst, postrm, prerm). Le script config doit poser toutes
les questions nécessaires à la configuration du paquet.
Remarque : il est un peu ennuyeux que dpkg considère le script postinst
du paquet comme un script de « configuration » du paquet ; en effet, un
paquet utilisant debconf est souvent pré-configuré, par son script
config, avant que le script postinst soit lancé. Mais, bon !
Lorsque le script config est lancé, deux paramètres lui sont passés ;
il en va de même pour le script postinst. Le premier est l’action à
effectuer et le second est la version du paquet actuellement installé.
Donc, comme pour un script postinst, vous pouvez utiliser
dpkg --compare-version sur $2 pour effectuer une action seulement en
cas de mise à niveau d’une version particulière du paquet ou d’autres
actions de ce type.
Le script config peut être lancé de l’une de ces trois façons :
1 Si un paquet est pré-configuré, avec dpkg-preconfigure, son
script config est lancé avec les paramètres « configure » et
« installed-version ».
2 Lorsque le script postinst d’un paquet est lancé, debconf
essaiera aussi de lancer le script config, avec les mêmes
paramètres que ceux qui sont passés lorsqu’il est pré-configuré.
C’est nécessaire car le paquet n’a peut-être pas été
pré-configuré, et donc le script config doit alors être lancé.
Veuillez consulter la section BIDOUILLES pour plus de
précisions.
3 Si un paquet est reconfiguré, avec dpkg-reconfigure, son script
config est lancé et les paramètres « reconfigure » et le numéro
de la version installée lui sont passés.
Notez que puisqu’une installation ou une mise à niveau typique
utilisant apt exécute les étapes 1 et 2, le script config sera lancé
deux fois. La seconde fois, il ne devrait rien faire (poser les
questions deux fois de suite est ennuyeux) et il devrait être nettement
idempotent. Par chance, debconf évite par défaut de répéter les
questions, donc c’est relativement facile à effectuer.
Notez que le script config est lancé avant que le paquet ne soit
dépaqueté. Il ne devrait utiliser que des commandes disponibles dans
les paquets essentiels. La seule dépendance qui est sûre d’être
satisfaite lorsque son script config est lancé est une dépendance
(éventuellement sur une version spécifique) sur debconf lui-même.
Le script config ne devrait pas avoir besoin de modifier le système de
fichiers. Il vérifie seulement l’état du système et pose des questions.
Debconf conserve alors les réponses, qui pourront être utilisées par le
script postinst. Et inversement, le script postinst ne devrait presque
jamais utiliser debconf pour poser des questions, mais devrait à la
place utiliser les réponses aux questions posées par le script config.
LE FICHIER TEMPLATES
Un paquet qui utilise debconf voudra probablement poser quelques
questions. Ces questions sont conservées sous une forme standard dans
le fichier templates.
Comme le script config, le fichier templates est inclus dans la section
control.tar.gz d’un paquet. Son format est semblable à celui du fichier
control Debian ; un ensemble de paragraphes séparés par des lignes
vides, où chaque paragraphe possède une forme du type RFC 822 :
Template: toto/tata
Type: string
Default: toto
Description: Il s’agit d’un exemple de question
Ceci est la description longue
.
Veuillez noter que :
- comme dans une description de paquet Debian, un point seul
définit un
nouveau paragraphe ;
- la plupart du texte est reformaté, mais le texte avec une
indentation
double est gardé tel quel, ainsi vous pouvez l’utiliser pour des
listes,
comme celle-ci. Soyez prudent, comme il n’est pas reformaté, s’il
est
trop large, il s’affichera mal. Il vaut mieux l’utiliser pour des
éléments courts (donc ceci est un mauvais exemple).
Template: toto/titi
Type: boolean
Description: C’est clair n’est-ce pas ?
Ceci est une autre question, de type booléenne.
Pour des exemples concrets de fichiers templates, regardez
/var/lib/dpkg/info/debconf.templates, ainsi que les autres fichiers
.templates de ce répertoire.
Examinons chaque champ successivement :
Template
Le nom du message, dans le champ « Template », est généralement
préfixé avec le nom du paquet. Ensuite, l’espace de nommage est
très libre ; vous pouvez utiliser une simple disposition plane,
ou définir des « sous-répertoires » contenant ces questions.
Type Le type du message détermine le type d’objet devant être
présenté à l’utilisateur. Les types actuellement reconnus sont :
string C’est un champ libre où l’utilisateur peut taper
n’importe quelle chaîne de caractères.
password
Demande à l’utilisateur un mot de passe. Utilisez-le avec
précaution ; soyez conscient que le mot de passe que
l’utilisateur indique sera écrit dans la base de données
de debconf. Vous devriez probablement effacer cette
valeur de la base de données dès que possible.
boolean
Un choix du type « vrai ou faux ».
select Un choix entre des valeurs. Les choix doivent être
spécifiés dans un champ nommé « Choices ». Les valeurs
sont séparées par des virgules et des espaces, comme
ceci :
Choices: oui, non, peut-être
multiselect
Comme le type de données select, excepté que
l’utilisateur peut choisir plusieurs éléments de la liste
(ou n’en choisir aucun).
note À la place d’une question, ce type de données indique une
note qui peut être affichée à l’utilisateur. Elle ne
devrait être utilisée que pour des notes importantes que
l’utilisateur doit absolument lire, car debconf va
déployer les grands moyens pour s’assurer que
l’utilisateur la lira ; en arrêtant l’installation et en
attendant qu’il presse une touche. Il est préférable de
n’utiliser ceci que pour signaler des problèmes très
sérieux et le type de données « error » est souvent plus
approprié.
error Ce type de données est utilisé pour les messages
d’erreur, comme des erreurs d’entrée invalide. Debconf
posera une question de ce genre même si la priorité est
trop haute, ou si l’utilisateur l’a déjà vue.
title Ce type de données est utilisé pour les titres, afin
qu’ils soient positionnés avec la commande SETTITLE.
text Ce type de données peut être utilisé pour des portions de
texte, comme des étiquettes, qui peuvent être utilisées
pour des raisons cosmétiques dans l’affichage de
certaines interfaces. D’autres interfaces ne
l’utiliseront pas. Il n’y a pas de raison de l’utiliser
pour l’instant, puisqu’aucune interface ne le gère
correctement. Il risque même d’être supprimé dans le
futur.
Default
Le champ « Default » indique à debconf la valeur par défaut.
Pour multiselect, elle peut être une liste de choix séparés par
des virgules semblable au champ « Choices ». Pour select, elle
devrait être l’un des choix possibles. Pour Boolean, c’est
« true » ou « false », alors que cela peut être n’importe quoi
pour une chaîne de caractères et est ignoré pour les mots de
passe.
Ne faites pas l’erreur de penser que le champ default contient
la « valeur » de la question, ou qu’il puisse être utilisé pour
changer la valeur de la question. Il ne le fait pas, et ne le
peut pas, il fournit seulement une valeur par défaut lorsqu’une
question est affichée pour la première fois. Pour fournir une
valeur par défaut qui change à la volée, vous devriez utiliser
la commande SET pour changer la valeur de la question.
Description
Le champ « Description », comme la description d’un paquet
Debian, est constitué de deux parties : une description courte
et une description longue. Notez que certaines interfaces
debconf n’affichent pas la description longue, ou ne l’affichent
que si l’utilisateur demande de l’aide. La description courte
doit donc suffire à la compréhension du message.
Si vous n’arrivez pas à trouver une description longue,
premièrement, réfléchissez-y plus longuement. Postez sur
debian-devel. Demandez de l’aide. Prenez votre plus belle
plume ! Car la description longue est importante. Si après tout
ça vous n’arrivez toujours pas à proposer quelque chose,
laissez-la vide. Cela n’apporte rien de recopier la description
courte.
Le texte dans la description longue sera reformaté, à moins
qu’il ne soit préfixé avec une espace supplémentaire (après
l’espace requise). Vous pouvez le découper en plusieurs
paragraphes en les séparant par " ." sur une ligne.
QUESTIONS
Une question est une instance d’un message. En demandant à debconf
d’afficher une question, votre script config peut interagir avec
l’utilisateur. Quand debconf charge un questionnaire (cela arrive à
chaque fois qu’un script postinst ou config est lancé), il crée
automatiquement la question à partir du message. Il est possible de
créer plusieurs questions indépendantes à partir d’un même message (en
utilisant la commande REGISTER), mais c’est rarement nécessaire. Les
messages sont des données statiques qui proviennent du fichier
templates, alors que les questions sont utilisées pour conserver des
données dynamiques, comme la valeur actuelle d’une question, ou si un
utilisateur a déjà vu une question, etc. Gardez bien à l’esprit la
différence entre un message et une question, mais ne vous inquiétez pas
trop.
MESSAGES PARTAGÉS
Il est tout à fait possible que des paquets partagent un message et une
question. Tous les paquets doivent fournir une copie identique du
message dans leur fichier templates. Cela peut être utile si un groupe
de paquets a besoin de poser les mêmes questions et que vous avez envie
de ne déranger les utilisateurs qu’une seule fois. Les messages
partagés sont généralement placés dans le pseudo-répertoire shared/
dans l’espace de nommage des questionnaires debconf.
LE PROTOCOLE DEBCONF
Les scripts config communiquent avec debconf en utilisant le protocole
debconf. C’est un protocole simple orienté ligne, semblable aux
protocoles internet courants comme SMTP. Le script config envoie à
debconf une commande en l’écrivant sur la sortie standard. Il peut
alors lire la réponse de debconf depuis l’entrée standard.
Les réponses de debconf peuvent être scindées en deux parties : un code
de retour numérique (le premier mot de la réponse) et un code de retour
étendu facultatif (le reste de la réponse). Le code numérique utilise 0
pour indiquer un succès et d’autres nombres pour indiquer divers types
d’erreur. Pour plus de précisions, veuillez consulter le tableau dans
les spécifications debconf de la charte Debian.
Le code de retour étendu n’a généralement aucune forme particulière,
vous pourrez donc, dans la plupart des cas, l’ignorer et vous ne
devriez pas essayer de l’analyser dans un programme pour savoir ce que
debconf est en train de faire. Les commandes comme GET sont des
exceptions car elles retournent une valeur dans le code de retour
étendu.
Vous voudrez généralement utiliser une bibliothèque spécifique à un
langage qui gère l’aspect pratique des connexions et des communications
avec debconf.
Maintenant, voici les commandes de ce protocole. Ce n’est pas une
définition complète, veuillez consulter les spécifications debconf de
la charte Debian pour plus d’informations.
VERSION nombre
Vous n’aurez, en général, pas besoin d’utiliser cette commande.
Elle échange avec le protocole debconf le numéro de la version
utilisée. La version actuelle du protocole est 2.0 et les
versions de la série 2.x assureront la compatibilité ascendante.
Vous pouvez spécifier le numéro de version du protocole que vous
parlez et debconf retournera la version du protocole qu’il parle
dans le code de retour étendu. Si la version que vous spécifiez
est trop faible, debconf renverra un code de retour numérique
égal à 30.
CAPB fonctionnalités
Vous n’aurez, en général, pas besoin d’utiliser cette commande.
Elle échange avec debconf une liste des fonctionnalités
reconnues. Des fonctionnalités supportées par vous et debconf
seront utilisées et debconf répondra avec toutes les
fonctionnalités qu’il accepte.
Si « escape » ne fait pas partie de vos fonctionnalités, debconf
va attendre que les commandes que vous lui passez comportent des
antislashes et des caractères de retour à la ligne échappés
(comme \\ et \n respectivement) et va faire de même pour ses
réponses. Ceci peut être utilisé par exemple pour changer des
chaînes de caractères multilignes en modèles, ou pour récupérer
des descriptions étendues multilignes de manière fiable en
utilisant METAGET.
TITLE chaîne de caractères
Cela positionne le titre de l’écran debconf affiché à
l’utilisateur. Vous n’aurez que rarement besoin de cette
commande puisque debconf peut automatiquement générer un titre
basé sur le nom de votre paquet.
SETTITLE question
Positionne le titre de la description courte du questionnaire
pour la question spécifiée. Le questionnaire devrait être du
type titre (« title »). Cela a pour avantage, par rapport à la
commande TITLE, de stocker les titres à la même place que le
reste des questions posées par debconf. Elle permet aussi de
traduire ces titres.
INPUT priorité question
Demande à debconf de préparer l’affichage d’une question à
l’utilisateur. La question n’est pas affichée jusqu’à ce que la
commande GO soit lancée ; cela permet de lancer plusieurs
commandes INPUT en série, pour construire un jeu de questions
qui pourraient toutes être posées sur un seul écran.
Le champ priorité indique à debconf s’il est important que la
question soit posée à l’utilisateur ou non. Les priorités sont :
low Éléments peu importants dont la valeur par défaut
convient dans la majorité des cas ; seuls ceux qui
veulent tout contrôler les voient ;
medium Éléments normaux qui ont une valeur par défaut
raisonnable ;
high Éléments qui n’ont pas de valeur par défaut raisonnable ;
critical
Éléments qui peuvent probablement casser le système sans
l’intervention de l’utilisateur.
Pour décider si la question doit être affichée ou non, debconf
se base sur sa priorité, si l’utilisateur l’a déjà vue et
l’interface qui va être utilisée. Si la question n’est pas à
afficher, debconf retournera un code de retour égal à 30.
GO
Cette commande demande à debconf d’afficher les questions
accumulées (depuis les commandes INPUT).
Si la fonctionnalité de sauvegarde est supportée et si
l’utilisateur indique qu’il veut revenir à une étape précédente,
debconf répondra avec un code de retour égal à 30.
CLEAR Élimine les questions accumulées (avec les commandes INPUT) sans
les afficher.
BEGINBLOCK
ENDBLOCK
Certaines interfaces peuvent afficher plusieurs questions à
l’utilisateur en même temps. Peut-être qu’à l’avenir une
interface pourra regrouper ces questions en blocs sur l’écran.
BEGINBLOCK et ENDBLOCK peuvent être placées autour de plusieurs
commandes INPUT pour indiquer des blocs de questions (les blocs
peuvent même être emboîtés). Étant donné qu’aucune interface
n’est encore aussi sophistiquée, ces commandes sont pour
l’instant ignorées.
STOP Cette commande dit à debconf que vous avez fini de communiquer
avec lui. En général, debconf peut détecter la fin de votre
programme, cette commande n’est donc pas nécessaire.
GET question
Après avoir utilisé INPUT et GO pour afficher une question, vous
pouvez utiliser cette commande pour récupérer la valeur indiquée
par l’utilisateur. Cette valeur est renvoyée dans le code de
retour étendu.
SET question valeur
Cette commande positionne la valeur d’une question et peut être
utilisée pour remplacer la valeur par défaut avec une valeur que
votre programme calcule à la volée.
RESET question
Cela remet la question à sa valeur par défaut (comme il est
spécifié dans le champ « Default » de son message).
SUBST question clé valeur
Des questions peuvent avoir des substitutions incluses dans
leurs champs « Description » et « Choices » (l’utilisation de
substitutions dans les champs « Choices » fait un peu
bidouillage, un meilleur mécanisme sera développé). Ces
substitutions ressemblent à « ${key} ». Quand les questions sont
affichées, les substitutions sont remplacées par leurs valeurs.
Cette commande peut être utilisée pour fixer la valeur d’une
substitution. Cela peut être utile si vous avez besoin
d’afficher à l’utilisateur des messages que vous ne pouvez pas
mettre dans le fichier templates.
N’essayez pas d’utiliser SUBST pour changer la valeur par défaut
d’une question ; cela ne fonctionnera pas puisqu’il y a la
commande SET prévue à cet effet.
FGET question marque
Une marque peut être associée à une question. Les marques
peuvent avoir une valeur « true » ou « false ». Cette commande
renvoie la valeur de la marque.
FSET question marque valeur
Cela fixe la valeur de la marque d’une question. La valeur est
soit « true » soit « false ».
La marque « seen » est courante. Elle n’est normalement
positionnée que si un utilisateur a déjà vu la question.
Habituellement, debconf affiche à l’utilisateur seulement les
questions dont la marque « seen » est positionnée à « false »
(ou si vous reconfigurez un paquet). Quelquefois vous voulez que
l’utilisateur revoie une question -- dans ce cas vous pouvez
positionner la marque « seen » à false pour forcer debconf à
l’afficher à nouveau.
METAGET question champ
Cela renvoie la valeur d’un champ d’une question associée à un
message (le champ Description, par exemple).
REGISTER message question
Cela crée une nouvelle question qui est liée à un message. Par
défaut, chaque message possède une question du même nom qui lui
est associée. Toutefois, on peut associer autant de questions
que l’on veut à un message et cela permet de créer beaucoup de
questions.
UNREGISTER question
Cela retire une question de la base de données.
PURGE Appelez cette commande dans votre script postrm lorsque votre
paquet est purgé. Il retire toutes les questions concernant
votre paquet de la base de données de debconf.
X_LOADTEMPLATEFILE /path/to/templates [owner]
Cette extensions charge le fichier de modèle spécifié dans la
base de données de debconf. Le propriétaire assume que le paquet
est en cours de configuration avec debconf.
Voici un exemple simple du protocole debconf en action.
INPUT medium debconf/frontend
30 question skipped
FSET debconf/frontend seen false
0 false
INPUT high debconf/frontend
0 question will be asked
GO
[ debconf affiche ici une question à l’utilisateur. ]
0 ok
GET no/such/question
10 no/such/question doesn’t exist
GET debconf/frontend
0 Dialog
BIBLIOTHÈQUES
Comme parler directement à debconf via son protocole représente trop de
travail, il existe quelques bibliothèques pour vous épargner cette
tâche ingrate.
Pour la programmation shell, il y a la bibliothèque
/usr/share/debconf/confmodule que vous pouvez inclure en début d’un
script shell ; vous pourrez communiquer avec debconf de façon presque
naturelle en utilisant la version en minuscules des commandes du
protocole debconf qui sont préfixées de « db_ » (par ex. « db_input »
et « db_go »). Pour plus de précisions veuillez consulter
confmodule(3).
Les programmeurs Perl peuvent utiliser le module perl
Debconf::Client::ConfModule(3) et les programmeurs Python peuvent
utiliser le module python debconf.
Le reste de ce manuel utilisera la bibliothèque
/usr/share/debconf/confmodule dans des scripts shell à titre d’exemple.
Voici un exemple de script config utilisant cette bibliothèque, il pose
seulement une question :
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
db_set mypackage/reboot-now false
db_input high mypackage/reboot-now || true
db_go || true
Remarquez l’utilisation de « || true » pour éviter que le script ne
meurt si debconf décide qu’il ne peut pas afficher une question, ou si
l’utilisateur essaie de revenir en arrière. Dans ces situations,
debconf renvoie un code de retour non nul et puisque set -e est
positionné dans ce script shell, un code de retour non intercepté le
fera abandonner.
Et voici le script postinst correspondant, qui utilise la réponse à la
question de l’utilisateur pour voir si le système doit être redémarré
(un exemple plutôt stupide) :
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
db_get mypackage/reboot-now
if [ "$RET" = true ]; then
shutdown -r now
fi
Remarquez l’utilisation de la variable $RET pour récupérer le code de
retour étendu de la commande GET, qui contient la réponse de
l’utilisateur à la question.
LE SCRIPT POSTINST
La dernière section avait un exemple de script postinst qui utilise
debconf pour récupérer la valeur d’une question et agir selon elle.
Voici quelques remarques à garder à l’esprit lors de l’écriture des
scripts postinst qui utilisent debconf :
* évitez de poser des questions dans le script postinst. Le script
config devrait poser ces questions à sa place en utilisant
debconf, pour que la pré-configuration fonctionne par la suite ;
* incluez toujours /usr/share/debconf/confmodule au début de votre
script postinst, même si vous ne lancez aucune des commandes
db_*. C’est nécessaire pour s’assurer que le script config sera
bien lancé (veuillez consulter la section BIDOUILLES pour plus
de détails) ;
* évitez d’afficher quelque chose sur la sortie standard dans
votre script postinst, puisque cela peut perturber debconf ; le
script postinst ne devrait de toute façon pas être bavard.
L’affichage sur la sortie d’erreur est autorisé, si vous le
devez ;
* si votre script postinst lance un démon, soyez sûr de dire à
debconf de STOPper à la fin, car debconf peut avoir du mal à
détecter la fin du script postinst ;
* faites accepter à votre script postinst un premier paramètre
« reconfigure ». Il peut le traiter comme « configure ». Cela
sera utilisé dans une version ultérieure de debconf pour
permettre aux scripts postinst de savoir quand ils sont
reconfigurés.
AUTRES SCRIPTS
En plus des scripts config et postinst, vous pouvez utiliser debconf
dans tout autre script d’administration. En général, vous utiliserez
debconf dans votre script postrm, pour appeler la commande PURGE quand
votre paquet est supprimé, pour vider ses entrées dans la base de
données de debconf. En fait, cela est automatiquement configuré pour
vous par dh_installdebconf(1).
Un emploi plus sophistiqué de debconf serait de l’utiliser dans le
script postrm lors de la purge de votre paquet, pour poser une question
concernant la suppression de quelque chose. Ou peut-être avez-vous
besoin de l’utiliser dans les scripts preinst ou prerm pour quelque
raison que ce soit. Toutes ces utilisations fonctionneront, bien
qu’elles impliqueront probablement de poser une question et d’agir en
fonction de la réponse dans le même programme, plutôt que de séparer
les deux actions comme dans les scripts config et postinst.
Notez que si votre paquet n’utilise debconf que dans le script postrm,
vous devriez faire en sorte que le script postinst de votre paquet
inclue /usr/share/debconf/confmodule, pour que debconf puisse charger
votre fichier templates dans sa base de données. Le questionnaire sera
alors disponible lorsque votre paquet sera purgé.
Vous pouvez aussi utiliser debconf dans d’autres programmes
indépendants. Le seul problème est que debconf n’est pas conçu pour
être un système d’enregistrement et ne peut pas être utilisé comme tel.
La philosophie d’Unix est préservée, les programmes sont configurés à
l’aide de fichiers dans /etc, et non pas par une sombre base de données
debconf (ce n’est qu’un cache et il peut se volatiliser). Réfléchissez
donc longuement avant d’utiliser debconf dans un programme indépendant.
Cela peut prendre un sens dans certains cas, comme dans le programme
apt-setup qui utilise debconf pour interroger l’utilisateur de manière
cohérente avec le reste de la procédure d’installation de Debian et qui
agit immédiatement avec les réponses pour configurer le fichier
sources.list.
LOCALISATION
Debconf accepte la localisation des fichiers templates. Cela est
accompli en ajoutant d’autres champs contenant les traductions. Tous
les champs peuvent être traduits. Par exemple, vous pourriez avoir
envie de traduire la description en espagnol. Créez simplement un champ
nommé « Description-es » contenant la traduction. Si un champ traduit
n’est pas disponible, debconf utilise le champ anglais.
En plus du champ « Description », vous devriez traduire le champ
« Choices » d’un message de type select ou multiselect. Il faut lister
les choix traduits dans l’ordre dans lequel ils apparaissent dans le
champ « Choices » principal. Vous ne devriez pas avoir besoin de
traduire le champ « Default » d’une question de type select ou
multiselect et la valeur de la question sera automatiquement retournée
en anglais.
Vous trouverez sûrement plus facile de gérer les traductions si vous
les conservez dans des fichiers séparés ; un fichier par traduction.
Par le passé, les programmes debconf-getlang(1) et
debconf-mergetemplate(1) étaient utilisés pour gérer les fichiers
debian/templates.ll. Cela a été rendu obsolète par le paquet
po-debconf, qui permet de traiter les traductions des questionnaires
debconf avec des fichiers .po comme les autres traductions. Vos
traducteurs vous remercieront pour l’utilisation de ce nouveau
mécanisme performant.
Pour plus de précisions sur po-debconf, veuillez regarder son fichier
README. Si vous utilisez debhelper, la conversion vers po-debconf est
aussi simple que de lancer la commande debconf-gettextize(1) une fois
et d’ajouter une dépendance de construction (« Build-Depends ») sur
po-debconf et sur debhelper (>= 4.1.13).
RÉCAPITULATION
Donc vous avez un script config, un fichier templates, un script
postinst qui utilisent debconf, etc. Réunir tous ces scripts dans un
paquet Debian n’est pas difficile. Vous pouvez le faire à la main ou
utiliser dh_installdebconf(1) qui fusionne vos questions-modèles
traduites, copie les fichiers à la bonne place pour vous et peut même
générer l’appel à PURGE qui devrait être placé dans votre script
postrm. Assurez-vous que votre paquet dépende de debconf (>= 0.5),
puisque les anciennes versions n’étaient pas compatibles avec tout ce
qui est décrit dans ce manuel. Et c’est terminé !
Mais vous ne pouvez pas encore tester, déboguer et utiliser debconf
pour des choses plus intéressantes que de poser de simples questions.
Pour cela, veuillez continuer à lire.
DÉBOGAGE
Vous avez donc un paquet qui est supposé utiliser debconf, mais il ne
fonctionne pas très bien. Peut-être que debconf ne pose pas la question
que vous avez configurée. Ou peut-être que quelque chose d’étrange
arrive ; il entre dans une boucle infinie, ou pire encore.
Heureusement, debconf possède beaucoup de possibilités de débogage.
DEBCONF_DEBUG
La première chose à portée de main est la variable
d’environnement DEBCONF_DEBUG. Si vous positionnez et exportez
DEBCONF_DEBUG=developer, debconf affichera sur la sortie
d’erreur standard (« stderr ») une copie du protocole debconf
lorsque votre programme s’exécute. Elle ressemblera à quelque
chose comme ceci -- la faute est flagrante :
debconf (developer): <-- input high debconf/frontand
debconf (developer): --> 10 "debconf/frontand" doesn’t exist
debconf (developer): <-- go
debconf (developer): --> 0 ok
Lors d’un débogage, l’interface readline de debconf est très
utile (d’après l’auteur), car les questions ne masquent pas cet
affichage, toute la sortie du débogage est facilement préservée
et enregistrée.
debconf-communicate
debconf-communicate(1) est un autre programme utile. Lancez-le
et vous pourrez parler le protocole debconf brut à debconf.
C’est une bonne manière d’essayer des choses à la volée.
debconf-show
Si un utilisateur rapporte un problème, debconf-show(1) peut
être utilisé pour lister les questions de votre paquet, en
affichant leurs valeurs et en indiquant si l’utilisateur les a
déjà vues.
.debconfrc
Pour éviter le cycle ennuyeux
construction/installation/débogage, il peut être utile de
charger vos questionnaires avec debconf-loadtemplate(1) et de
lancer votre script config à la main avec la commande
debconf(1). Néanmoins, vous devez toujours le faire en tant que
superutilisateur, d’accord ? Pas terrible ! Et idéalement vous
souhaiteriez être en mesure de voir à quoi ressemble une
installation toute fraîche de votre paquet avec une base de
données debconf propre.
Il s’avère que si vous configurez un fichier ~/.debconfrc pour
un utilisateur normal, pointant vers un config.dat et un
template.dat propres à l’utilisateur, vous pouvez charger les
questionnaires et lancer tous les scripts config que vous
voulez, sans avoir besoin d’un accès super-utilisateur. Si vous
voulez commencer avec une base de données propre, supprimez
simplement les fichiers *.dat.
Pour plus de détails pour mettre cela en place, voyez
debconf.conf(5), et remarquez que /etc/debconf.conf fait un bon
modèle pour un fichier ~/.debconfrc personnel.
PROGRAMMATION AVANCÉE AVEC DEBCONF
Manipulation du fichier de configuration
Beaucoup d’entre vous ont l’air de vouloir utiliser debconf pour aider
à la gestion des fichiers de configuration contenus dans vos paquets.
Peut-être qu’il n’y a pas de bonne valeur par défaut à inclure dans
votre paquet, vous voulez donc utiliser debconf pour interroger
l’utilisateur et écrire un fichier de configuration basé sur ses
réponses. Cela semble assez facile à faire, mais lorsque vous
considérez les mises à niveau, que faire lorsque quelqu’un modifie le
fichier de configuration que vous générez, et dpkg-reconfigure, et...
Il y a beaucoup de manières de le faire, la plupart d’entre-elles ne
sont pas correctes et vous serez souvent ennuyé par des rapports de
bogue. Voici une manière correcte de le faire. Cela suppose que votre
fichier config n’est composé que d’une série de variables de shell
positionnées, avec des commentaires entre elles, vous pouvez simplement
inclure le fichier pour le « charger ». Si vous avez un format plus
compliqué, sa lecture (et son écriture) devient un peu plus délicate.
Votre script config ressemblera à quelque chose comme ça :
#!/bin/sh
CONFIGFILE=/etc/foo.conf
set -e
. /usr/share/debconf/confmodule
# charge le fichier de configuration, s’il existe.
if [ -e $CONFIGFILE ]; then
. $CONFIGFILE || true
# Enregistrer les valeurs du fichier de configuration
# dans la base de données de debconf
db_set mypackage/toto "$FOO"
db_set mypackage/titi "$BAR"
fi
# Poser les questions.
db_input medium mypackage/toto || true
db_input medium mypackage/titi || true
db_go || true
Et le script postinst ressemblera à quelque chose comme ceci :
#!/bin/sh
CONFIGFILE=/etc/foo.conf
set -e
. /usr/share/debconf/confmodule
# Générer un fichier de configuration, s’il n’en existe pas.
# Une alternative est d’effectuer une copie dans un fichier
# modèle depuis un autre endroit.
if [ ! -e $CONFIGFILE ]; then
echo "# Fichier de configuration pour mon paquet" > $CONFIGFILE
echo "TOTO=" >> $CONFIGFILE
echo "TITI=" >> $CONFIGFILE
fi
# Substituer les valeurs par celles de la base
# de données de debconf. Des optimisations
# évidentes sont possibles ici. Le cp avant
# le sed permet de s’assurer que l’on ne détruit
# pas le système des droits du fichier config.
db_get mypackage/foo
TOTO="$RET"
db_get mypackage/bar
TITI="$RET"
cp -a -f $CONFIGFILE $CONFIGFILE.tmp
# Si l’administrateur a supprimé ou commenté des variables mais
# les a ensuite définies via debconf, ajouter (à nouveau) au
# fichier de configuration (conffile).
test -z "$TOTO" || grep -Eq ’^ *TOTO=’ $CONFIGFILE || \
echo "TOTO=" >> $CONFIGFILE
test -z "$TITI" || grep -Eq ’^ *TITI=’ $CONFIGFILE || \
echo "TITI=" >> $CONFIGFILE
sed -e "s/^ *TOTO=.*/TOTO=\"$TOTO\"/" \
-e "s/^ *TITI=.*/TITI=\"$TITI\"/" \
< $CONFIGFILE > $CONFIGFILE.tmp
mv -f $CONFIGFILE.tmp $CONFIGFILE
Examinez comment ces deux scripts gèrent tous les cas. Sur une nouvelle
installation, les questions sont posées par le script config et un
nouveau fichier de configuration est généré par le script postinst.
Pendant les mises à niveau et les reconfigurations, le fichier config
est lu, et ses valeurs sont utilisées pour modifier les valeurs dans la
base de données de debconf : les modifications manuelles de
l’administrateur ne sont donc pas perdues. Les questions sont posées à
nouveau (et peuvent être affichées ou non). Puis le script postinst
remplace les valeurs dans le fichier config, en laissant le reste du
fichier inchangé.
Permettre à l’utilisateur de revenir en arrière
Peu de choses sont plus frustrantes, quand vous utilisez un système
comme debconf, que de répondre à une question posée, puis de passer à
un autre écran avec une nouvelle question, de réaliser alors que vous
avez fait une erreur dans la dernière question et que vous voulez y
retourner mais vous découvrez que vous ne le pouvez pas.
Puisque debconf est conduit par votre script config, il ne peut revenir
seul à une question précédente, mais avec un petit coup de pouce de
votre part, il peut le faire. La première étape est que votre script
config fasse savoir à debconf qu’il est capable de gérer le fait que
l’utilisateur presse un bouton de retour en arrière. Vous utiliserez la
commande CAPB pour le faire en passant backup en paramètre.
Puis, après chaque commande GO, vous devez essayer de voir si
l’utilisateur a demandé à revenir en arrière (debconf renvoie un code
de retour 30) et si c’est le cas, revenir à la question précédente.
Il existe plusieurs manières d’écrire des structures de contrôle pour
que votre programme puisse revenir aux questions antérieures lorsque
c’est nécessaire. Vous pouvez écrire du code spaghetti plein de goto.
Ou vous pouvez créer plusieurs fonctions et les utiliser de manière
récursive. Mais peut-être que la façon la plus correcte et la plus
simple est de construire une machine à états. Voici le squelette d’une
machine à états que vous pouvez remplir et améliorer.
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
db_capb backup
STATE=1
while true; do
case "$STATE" in
1)
# Deux questions sans rapport.
db_input medium ma/question || true
db_input medium mon/autre_question || true
;;
2)
# Ne poser cette question que si la
# réponse à la première question était oui.
db_get ma/question
if [ "$RET" = "true" ]; then
db_input medium ma/question_dependante || true
fi
;;
*)
# Le cas par défaut est atteint quand $STATE est plus
# grand que le dernier état implémenté, et provoque la
# sortie de boucle. Ceci requiert que les état soient
numérotés
# à partir de 1, successivement, et sans trou, puisque
# l’on entrera dans le cas par défaut s’il y a un trou
# dans la numérotation
break # quitte la boucle "while" ;;
esac
if db_go; then
STATE=$(($STATE + 1))
else
STATE=$(($STATE - 1))
fi
done
if [ $STATE -eq 1 ]; then
# L’utilisateur a demandé à revenir en arrière,
# alors qu’il était à la première question. Ce cas est
# problématique. L’installation normale des paquets
# dpkg et apt n’est pas capable de revenir en arrière
# vers les questions d’autres paquets, à l’heure où ceci
# est écrit, donc cela va provoquer la sortie, laissant
# les paquets non configurés - ce qui est probablement la
# meilleure façon de gérer la situation.
exit 10
fi
Notez que si tout ce que fait votre script config est de poser quelques
questions sans rapport les unes avec les autres, il n’y a pas besoin
d’une machine à états. Posez simplement toutes les questions et GO ;
debconf fera de son mieux pour les présenter toutes sur un écran et
l’utilisateur n’aura pas besoin de revenir en arrière.
Éviter les boucles infinies
Une chose très agaçante peut arriver avec debconf si vous avez une
boucle dans votre script. Supposez que vous demandiez une entrée et que
vous la validiez, ou que vous effectuiez une boucle si elle n’est pas
valable :
ok=”
do while [ ! "$ok" ];
db_input low toto/titi || true
db_go || true
db_get toto/titi
if [ "$RET" ]; then
ok=1
fi
done
Cela parait correct au premier coup d’oeil. Mais pensez à ce qui va
arriver si la valeur de toto/titi est "" lorsque l’on entre dans cette
boucle et que l’utilisateur a fixé la priorité à high, ou s’il utilise
une interface non interactive et qu’on ne lui demande donc aucune
entrée. La valeur de toto/titi n’est pas changée par db_input et donc
le test échoue et boucle. Et boucle...
Une solution à ce problème est de s’assurer qu’avant l’entrée dans la
boucle, la valeur de toto/titi est positionnée à quelque chose qui
permettra de passer le test de la boucle. Donc par exemple si la valeur
par défaut de toto/titi est « 1 », vous pourrez passer la commande
RESET toto/titi juste avant d’entrer dans la boucle.
Une autre solution serait de vérifier la valeur du code de retour de la
commande INPUT. Si c’est 30, l’utilisateur ne verra alors pas la
question qui lui est posée et vous devriez sortir de la boucle.
Choisir parmi plusieurs paquets liés
Parfois, un ensemble de paquets liés peuvent être installés et vous
voulez demander à l’utilisateur lequel doit être utilisé par défaut.
Les dictionnaires, ispell ou les gestionnaires de fenêtres sont des
exemples de tels jeux de paquets.
Bien qu’il pourrait être possible de simplement demander « Ce paquet
doit-il être celui par défaut ? » pour chaque paquet de l’ensemble,
cela aboutit à un grand nombre de questions répétitives si plusieurs de
ces paquets sont installés. Avec debconf, il est possible d’afficher
une liste de tous les paquets de l’ensemble et d’autoriser
l’utilisateur à choisir l’un d’entre eux. Et voici comment.
Utilisez un message partagé par tous les paquets de cet ensemble.
Quelque chose comme ceci :
Template: shared/window-manager
Type: select
Choices: ${choices}
Description: Choisissez une gestionnaire de fenêtres par défaut
Veuillez choisir le gestionnaire de fenêtres qui sera démarré par
défaut
lors du lancement de X.
Description: Select the default window manager.
Select the window manager that will be started by
default when X starts.
Chaque paquet devrait inclure une copie de ce message. Puis il devrait
inclure du code comme ceci dans son script config :
db_metaget shared/window-manager owners
OWNERS=$RET
db_metaget shared/window-manager choices
CHOICES=$RET
if [ "$OWNERS" != "$CHOICES" ]; then
db_subst shared/window-manager choices $OWNERS
db_fset shared/window-manager seen false
fi
db_input medium shared/window-manager || true
db_go || true
Une petite explication est nécessaire. Pour l’instant votre script est
lancé, debconf a déjà lu tous les questionnaires des paquets qui vont
être installés. Puisque tous ces paquets ont une question en commun,
debconf enregistre ce fait dans le champ owners. Par une étrange
coïncidence, le format du champ owners est le même que celui du champ
choices (une liste de valeurs séparées par virgule et espace).
La commande METAGET peut être utilisée pour récupérer la liste des
propriétaires (« owners ») et la liste des choix. S’ils sont
différents, un nouveau paquet est alors installé. Utilisez alors la
commande SUBST pour modifier la liste des choix afin qu’elle soit
identique à celle des propriétaires et posez la question.
Lorsqu’un paquet est supprimé, vous voudrez probablement voir si ce
paquet est le choix actuellement sélectionné et s’il l’est, demander à
l’utilisateur de sélectionner un autre paquet pour le remplacer.
Cela peut être accompli en ajoutant quelque chose comme ceci dans le
script prerm de tous les paquets liés (en remplaçant <paquet> par le
nom du paquet) :
if [ -e /usr/share/debconf/confmodule ]; then
. /usr/share/debconf/confmodule
# Je ne veux plus de cette question.
db_unregister shared/window-manager
# Regarde si la question partagée existe toujours.
if db_get shared/window-manager; then
db_metaget shared/window-manager owners
db_subst shared/window-manager choices $RET
db_metaget shared/window-manager value
if [ "<paquet>" = "$RET" ] ; then
db_fset shared/window-manage seen false
db_input high shared/window-manager || true
db_go || true
fi
# Maintenant faites ce que le script postinst faisait
# pour mettre à jour le lien symbolique du gestionnaire de
# fenêtre.
fi
fi
BIDOUILLES
Debconf n’est pas encore entièrement intégré à dpkg (mais je veux
changer ça), cela demande donc actuellement quelques bidouilles peu
propres.
Le pire de ces bidouillages est le lancement du script config. Le
fonctionnement actuel est de lancer le script config lorsque le paquet
est pré-configuré. Puis, lorsque le script postinst s’exécute, il lance
debconf. Debconf remarque qu’il va être utilisé par le script postinst,
il s’arrête et lance le script config. Cela ne fonctionne que si votre
script postinst charge l’une des bibliothèques debconf, les scripts
postinst doivent toujours prendre soin de les charger. Nous espérons
nous attaquer à cela plus tard en ajoutant un support explicite de
debconf dans dpkg. Le programme debconf(1) est une étape dans ce sens.
Une bidouille similaire est de lancer debconf lorsqu’un script config,
postinst, ou d’autres programmes qui l’utilisent commence. Après tout,
ils espèrent avoir la possibilité de communiquer avec debconf d’une
façon correcte. Pour l’instant, la manière dont cela est accompli est
que lorsqu’un tel script charge une bibliothèque debconf (comme
/usr/share/debconf/confmodule) et que debconf n’est pas déjà lancé, il
est démarré et une nouvelle copie du script est ré-exécutée. Le seul
résultat perceptible est que vous avez besoin de mettre la ligne qui
charge une bibliothèque debconf au tout début du script, ou des choses
étranges arriveront. Nous espérons examiner ça plus tard en changeant
l’invocation de debconf et le changer en un démon provisoire.
La façon dont debconf trouve quels fichiers templates charger et quand
les charger ressemble vraiment à une bidouille. Lorsque les scripts
config, preinst et postinst invoquent debconf, il trouvera
automatiquement l’emplacement du fichier templates et le chargera. Les
programmes indépendants qui utilisent debconf forceront debconf à
rechercher les fichiers templates dans
/usr/share/debconf/templates/nomduprog.templates. Et si un le script
postrm veut utiliser debconf au moment de la purge, les questionnaires
ne seront pas disponibles à moins que debconf ait une opportunité de
les charger dans son script postinst. Cela n’est pas très propre mais
presque inévitable. Dans le futur, certains de ces programmes
pourraient malgré tout avoir la possibilité d’utiliser
debconf-loadtemplate à la main.
Le comportement historique de /usr/share/debconf/confmodule de jouer
avec les descripteurs de fichier et de configurer un descripteur de
fichier spécial (« fd #3 ») qui communique avec debconf, peut causer
toutes sortes de trouble lorsqu’un démon est lancé par un script
postinst, puisque le démon cesse de communiquer avec debconf et que
debconf ne peut pas savoir quand le script se termine. La commande STOP
peut être utilisée pour ceci. Nous envisagerons plus tard de faire
passer la communication avec debconf à travers une socket ou un autre
mécanisme que les entrées et sorties standard.
Debconf positionne DEBCONF_RECONFIGURE=1 avant de lancer les scripts
postinst, donc un script postinst voulant éviter des opérations
coûteuses lorsqu’il est reconfiguré peut regarder cette variable. C’est
une bidouille car la meilleure chose à faire serait de lui passer $1 =
"reconfigure", mais le faire sans casser tous les scripts postinsts qui
utilisent debconf est difficile. Le projet de migration pour cette
bidouille est d’encourager les gens à écrire des scripts postinst qui
acceptent "reconfigure" et, une fois qu’ils le feront tous, commencer à
passer cette variable.
VOIR AUSSI
debconf(7) est le guide de l’utilisateur de debconf.
La spécification debconf dans la charte Debian est une définition
canonique du protocole debconf.
/usr/share/doc/debian-policy/debconf_specification.txt.gz
debconf.conf(5) contient beaucoup d’informations, y compris des
informations sur les pilotes de la base de données.
AUTEUR
Joey Hess <joeyh@debian.org>
TRADUCTION
Julien Louis <ptitlouis@sysif.net>, 2005
Cyril Brulebois <cyril.brulebois@enst-bretagne.fr>, 2006
DEBCONF-DEVEL(7)