Provided by: debconf-doc_1.5.66ubuntu1_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-versions 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 (séparées par des espaces). 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.
SETTITLE question
Utilisez la description courte du message comme titre de l'écran debconf pour la question
indiquée. Le message devrait être de type titre. 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.
Définir le titre depuis un message signifie que les titres seront stockés à la même place que les
autres questions posées par debconf. Elle permet aussi de traduire ces titres.
TITLE chaîne de caractères
Utiliser la chaîne de caractères comme titre de l'écran debconf. L'utilisation de la commande
SETTITLE est préférable car elle permet de traduire les titres affichés par debconf.
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(3pm) 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 purgé, 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(7), 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, consultez sa page de manuel. 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_C_VALUES
Si cette variable d'environnement est définie à « true », l'interface graphique affichera les
valeurs dans les champs « Choices-C » (s'ils sont présents) des modèles select et multi-select au
lieu des valeurs compréhensibles.
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 la 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 0 ]; then
# L'utilisateur a demandé à revenir à la première
# question. Ce cas est problématique. L'installation
# normale des paquets avec 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'œil. 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-manager 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 ce paramètre.
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 <kibi@debian.org>, 2006
Veuillez signaler toute erreur de traduction en écrivant à <debian-l10n-french@lists.debian.org> ou par
un rapport de bogue sur le paquet debconf.
DEBCONF-DEVEL(7)