table of contents
DEBCONF-DEVEL(7) | Miscellaneous Information Manual | DEBCONF-DEVEL(7) |
NOMBRE¶
debconf - Guía del desarrollador
DESCRIPCIÓN¶
Esta es una guía para el desarrollo de paquetes que usan debconf.
Este manual asume que está familiarizado con debconf como usuario, y que conoce los conceptos básicos de la construcción de paquetes debian.
Este manual comienza explicando dos nuevos ficheros que se añaden a paquetes debian que usan debconf. A continuación, explica cómo funciona el protocolo de debconf, y señala las bibliotecas que permitirán que sus programas hablen tal protocolo. Se discuten otros scripts de desarrollador que habitualmente usan debconf: los scripts postinst (postinstalación) y postrm (posteliminación). Continua con temas más avanzados como el sistema de plantillas compartidas de debconf, depuración de fallos, y algunas técnicas comunes y problemas a la hora de programar con debconf. Finaliza con un análisis de las deficiencias actuales de debconf.
EL SCRIPT CONFIG¶
Debconf añade un script de desarrollador adicional, el script «config», al conjunto de scripts de desarrollador que pueden existir en paquetes debian («postinst», «preinst», «postrm», y «prerm»). El script «config» es el responsable de plantear cualquier pregunta necesaria para la configuración del paquete.
Nota: Es un poco confuso que dpkg se refiere a ejecutar el script «postinst» como la «configuración» del paquete, ya que, habitualmente, un paquete que usa debconf está totalmente preconfigurado mediante el script «config» antes de que se ejecute el script de postinstalación. Pero bueno.
Al igual que el script «postinst», el script «config» acepta dos parámetros cuando se ejecuta. El primero dice la acción que se está realizando, y el segundo la versión del paquete actualmente instalado. Por lo tanto, al igual que con un script «postinst», puede usar «dpkg --compare-versions» con «$2» para hacer que un comportamiento sólo aparezca durante la actualización a partir de una versión en particular, y otros comportamientos parecidos.
El script «config» se puede ejecutar de tres formas distintas:
- 1
- Si el paquete está preconfigurado con «dpkg-preconfigure», se ejecuta el script «config» y se le introducen los parámetros «configure» y la versión instalada («installed-version»).
- 2
- Cuando se ejecuta el script «postinst» de un paquete debconf intentará ejecutar también el script «config», al que se le introducirán los mismos parámetros que se introducen cuando se preconfigura. Es necesario ya que puede que el paquete aún no se haya preconfigurado, y que el script «config» todavía necesite una oportunidad para ejecutarse. Para más detalles consulte «ARREGLOS».
- 3
- Si el paquete se reconfigura con «dpkg-reconfigure», se ejecuta el script «config», y se le introducen los parámetros «reconfigure» y la versión instalada («installed-version»).
Tenga en cuenta que ya que una instalación o actualización típica de paquetes mediante apt ejecuta los pasos 1 y 2, el script «config» se ejecutará dos veces. No debería hacer nada (plantear las mismas preguntas dos veces seguidas es molesto), y debería ser idempotente. Afortunadamente, debconf evita repetir preguntas por omisión, así que esto es generalmente fácil de realizar.
Observe que el script «config» se ejecuta antes de desempaquetar el paquete. Sólo debería usar órdenes que están en los paquetes esenciales («essential»). La única dependencia que su paquete tendrá de forma obligatoria al ejecutar el script «config» es el mismo debconf (posiblemente versionada).
El script «config» no debería necesitar modificar el sistema de ficheros de ninguna forma. Simplemente, examina el estado del sistema y plantea preguntas, y debconf guarda las respuestas para usarlas después a través del script «postinst». Por el contrario, el script «postinst» nunca debería usar debconf para plantear preguntas, sino que debería actuar en base a las respuestas a las preguntas planteadas por el script «config».
EL FICHERO DE PLANTILLAS¶
Probablemente, un paquete que usa debconf desea plantear algunas preguntas. Estas preguntas se guardan, en de plantilla, en el fichero de plantillas.
Al igual que el script «config», el fichero de plantillas se ubica en la sección «control.tar.gz» de un paquete «.deb». Su formato es similar al fichero de control de debian, un conjunto de definiciones separadas por líneas en blanco. Cada definición tiene una forma similar al formato RFC822:
Template: foo/bar
Type: string
Default: foo
Description: Este es un ejemplo de pregunta de tipo cadena.
Esta es su descripción extendida.
.
Tenga en cuenta:
- Al igual que en la descripción de un paquete debian,
un punto en una línea vacía inicia un nuevo párrafo.
- La mayoría del texto se justifica, pero el texto con
doble sangrado no se modifica, así que puede usarlo
para listas de elementos como esta lista. Tenga
cuidado ya que no se justifica, y tendrá un pobre
aspecto si es demasiado ancho. Es mejor usarlo con
elementos cortos (y por ello éste es un mal ejemplo).
Template: foo/baz
Type: boolean
Description: Es obvio, ¿no?
Esta es otra pregunta, de tipo booleano.
Si desea ver ejemplos de uso reales de ficheros de plantillas consulte «/var/lib/dpkg/info/debconf.templates» y otros ficheros «.templates» en ese directorio.
Ahora vamos a explicar cada uno de los campos.
- Template
- El nombre de la plantilla, en el campo «Template», tiene habitualmente como prefijo el nombre del paquete. A continuación de esto, el espacio de nombres está abierto; puede usar un sencillo diseño plano como el que aparece antes, o definir «subdirectorios», que contienen las preguntas relacionadas.
- Type
- El tipo de plantilla determina el tipo de elemento que se muestra al usuario. Los tipos aceptados actualmente son:
- string
- Resulta en un campo de entrada con formato libre en el que el usuario puede introducir cualquier cadena.
- password
- Solicita una contraseña al usuario. Úselo con precaución; tenga en cuenta que la contraseña que el usuario introduzca se escribirá en la base de datos de debconf. Probablemente, debería eliminar ese valor de la base de datos tan pronto como sea posible.
- boolean
- Una elección «true/false» (verdadero/falso).
- select
- Una elección de un valor entre un número de valores. Las posibles elecciones se deben definir en un campo llamado «Choices». Separe los valores posibles con comas y espacios, como se ve a continuación.
Choices: yes, no, maybe
- multiselect
- Similar al tipo datos «select», a excepción de que el usuario puede seleccionar cualquier número de elementos de la lista de elecciones (o no seleccionar ninguno).
- note
- Más que una pregunta, este tipo de dato indica una nota que se puede mostrar al usuario. Sólo se debería usar para notas importantes que el usuario realmente debería ver, ya que debconf sufrirá complicaciones para asegurarse de que el usuario lo ve; interrumpirá la instalación para que puedan pulsar una tecla. Es mejor usar este aviso sólo para problemas serios, y a menudo es más adecuado usar el tipo de dato «error» .
- error
- Este tipo de dato se usa para mensajes de error, tales como los errores de validación de entradas. Debconf mostrará una pregunta de este tipo incluso si la prioridad es demasiado alta o si el usuario ya la ha visto.
- title
- Este tipo de datos se usa para títulos, que se definirán con la orden «SETTITLE».
- text
- Este tipo de datos se puede usar para fragmentos de texto tales como etiquetas, que se pueden usar por razones estéticas en las ventanas de algunas interfaces. Otras interfaces no harán uso de él. Aún no existe ninguna razón para usar este tipo de dato ya que ninguna interfaz lo permite de forma adecuada. Incluso puede que se elimine en el futuro.
No cometa el error de pensar que el campo «Default» contiene el valor de la pregunta, o que se puede usar para cambiar el valor de la pregunta. No puede hacer esto, y no debería. Simplemente ofrece el valor predefinido para la primera vez que se muestra la pregunta. Para proporcionar un valor predefinido que se pueda modificar en el momento, tendrá que usar la orden «SET» para cambiar el valor de una pregunta.
Si no puede inventarse una descripción larga, primero, piense un poco más. Mande un correo a debian-devel. Pida ayuda. ¡Tome clases de composición de texto! La descripción extendida es importante. Si después de todo esto aún no se le ha ocurrido nada, deje el espacio en blanco. No tiene sentido duplicar la descripción corta.
El texto de la descripción extendida se justificará, a menos que esté precedido por un espacio blanco adicional (además del espacio requerido). Puede dividirlo en varios párrafos insertando «.» en una línea vacía entre los párrafos.
PREGUNTAS¶
Una pregunta es una instancia de plantilla. Al pedir a debconf que muestre una pregunta, su script «config» puede interactuar con el usuario. Cuando debconf carga un fichero de plantillas (esto ocurre cada vez que se ejecuta un script «config» o «postinst») automáticamente crea una instancia para cada pregunta de cada plantilla. Es posible crear instancias de varias preguntas independientes a partir de la misma plantilla (usando la orden «REGISTER»), pero rara vez es necesario. Las plantillas son datos estáticos que proceden del fichero de plantillas, mientras que las preguntas se usan para almacenar datos dinámicos, tales como el valor actual de la pregunta, si el usuario ha visto la pregunta, y así en adelante. Tenga en cuenta la diferencia entre una plantilla y una pregunta, pero no se preocupe demasiado por ello.
PLANTILLAS COMPARTIDAS¶
Es posible tener una plantilla y una pregunta compartidas por un conjunto de paquetes. Todos los paquetes deben proporcionar una copia idéntica de la plantilla en sus ficheros de plantillas. Puede ser útil si un conjunto de paquetes necesitan plantear la misma pregunta, y sólo desea consultar al usuario una sola vez. Habitualmente, las plantillas compartidas se ubican en el seudo directorio «shared/» en el espacio de nombres («namespace») de la plantilla de debconf.
EL PROTOCOLO DE DEBCONF¶
Los scripts «config» se comunican con debconf usando el protocolo de debconf. Éste es un sencillo protocolo orientado a la línea de órdenes, similar a protocolos comunes de Internet tales como SMTP. El script «config» envía una orden a debconf enviando la orden por la salida estándar. A continuación, puede leer la respuesta de debconf por la entrada estándar.
La respuesta de debconf se puede dividir en dos partes. Un código de salida numérico (la primera palabra de la respuesta), y opcionalmente un código de salida extendido (el resto de la respuesta). El código numérico usa cero para indicar éxito, y otros números para indicar varios tipos de fallo. Para más detalles, consulte la tabla en el documento de especificaciones de debconf en las normas de Debian (debian-policy).
El código de salida extendido tiene, habitualmente, una forma libre y sin especificar, así que generalmente debería ignorarlo, y definitivamente no debería intentar analizarlo con un programa para averiguar lo que debconf está haciendo. La excepción son órdenes como «GET», que hacen que un valor se devuelva en el código de salida extendido.
Habitualmente, querrá usar una biblioteca de lenguaje específico que gestiona los particularidades de creación de estas conexiones con debconf y la comunicación con éste.
Por ahora, aquí tiene las órdenes en el protocolo. Esta no es la definición completa; para ello, consulte el documento de especificaciones de debconf en las normas de Debian (debian-policy).
- VERSION número
- Generalmente no tendrá que usar esta orden. Intercambia con debconf el número de versión del protocolo que se está usando. La versión del protocolo actual es 2.0, y las versiones de la serie 2.x tendrán compatibilidad hacia atrás. Puede definir el número de versión del protocolo que está usando y debconf devolverá la versión del protocolo que está usando en el código de salida extendido. Si la versión que define es demasiado baja, debconf responderá con el código numérico 30.
- CAPB funcionalidades
Si «escape» está entre sus funcionalidades, debconf esperará que las órdenes que envíe tengan escapes de barras inversas y nuevas líneas (como «\\» y «\n» respectivamente), y responderá con barras inversas y nuevas líneas escapadas. Esto se puede usar, por ejemplo, para sustituir cadenas de varias líneas en plantillas, o para obtener descripciones extendidas de varias líneas adecuadamente usando METAGET. Si usa este modo, tendrá que escapar el texto de entrada (o puede usar debconf-escape(1) para que le asista en esta labor si así lo desea), pero las bibliotecas confmodule devolverán respuestas sin escapes.
Configurar el título a partir de la plantilla significa que se guardan en la misma ubicación que el resto de las preguntas de debconf, permitiendo su traducción.
- TITLE cadena
- Esto define el título que debconf muestra al usuario con la cadena especificada. Habitualmente, se prefiere el uso de la orden «SETTITLE» ya que permite la traducción del título.
- INPUT prioridad pregunta
El campo de prioridad indica a debconf la importancia de la pregunta mostrada al usuario. Los valores de prioridad son:
- low
- Elementos muy triviales que tienen valores predefinidos que funcionarán en la inmensa mayoría de los casos. Sólo los obsesos del control deberían verlos.
- medium
- Elementos normales con valores predefinidos razonables.
- high
- Elementos que no tienen un valor predefinido razonable.
- critical
- Elementos que posiblemente rompan el sistema sin la intervención del usuario.
Debconf decide si se muestra la pregunta en base a la prioridad, si el usuario la ha visto ya, y la interfaz que se está usando. Si la pregunta no se va a mostrar, debconf responde con el código numérico 30.
Si se admite la funcionalidad de copia de seguridad y el usuario indica que desea retroceder, debconf responde con el código numérico 30.
- CLEAR
- Elimina el conjunto acumulado de preguntas (de órdenes «INPUT») sin mostrarlas.
- BEGINBLOCK
- ENDBLOCK
- Algunas interfaces de debconf pueden mostrar varias preguntas a la vez al usuario. Puede que en el futuro, una interfaz sea también capaz de agrupar en bloque estas preguntas en la pantalla. «BEGINBLOCK» y «ENDBLOCK» se pueden ubicar en torno a un conjunto de órdenes «INPUT» para indicar bloques de preguntas (y los bloques se pueden anidar también). Ya que ninguna interfaz de debconf es aún tan sofisticada, estas órdenes se ignorarán por ahora.
- STOP
- Esta orden indica a debconf que ya ha terminado de comunicarse con él. Habitualmente debconf puede detectar la finalización de su programa, con lo cual esta orden no sería necesaria.
- GET pregunta
- Después de usar «INPUT» y «GO» para mostrar una pregunta, puede usar esta orden para obtener el valor que introdujo el usuario. El valor se devuelve en el código de salida extendido.
- SET pregunta valor
- Define el valor de la pregunta, y se puede usar para reemplazar el valor predefinido con un cálculo que su programa haga durante el proceso.
- RESET pregunta
- Restablece la pregunta a su valor predefinido (tal y como está definido en el campo «Default» de su plantilla).
- SUBST pregunta clave valor
- Las preguntas pueden integrar sustituciones en sus campos «Description» y «Choices» (el uso de sustituciones en campos «Choices» no está demasiado bien hecho; con el tiempo se desarrollará un mecanismo mejor). Estas sustituciones tiene la apariencia «${key}». Cuando se muestra la pregunta, las sustituciones se reemplazan con sus valores. Esta orden se puede usar para definir el valor de una sustitución. Es útil si necesita mostrar algunos mensajes al usuario, las cuales no desea integrar en el código («hardcode») en el fichero de plantillas.
- No intente usar «SUBST» para cambiar el valor predefinido de una pregunta; no funcionará ya que existe una orden «SET» para ese propósito.
- FGET pregunta marca
- Las preguntas pueden tener marcas asociadas a ellas. Las marcas pueden tener un valor de «true» (verdadero) o «false» (falso).
- FSET pregunta marca valor
Una marca común es la marca «seen». Habitualmente, sólo se define si el usuario ya ha viso la pregunta. Generalmente, debconf sólo muestra preguntas a los usuarios si la marca «seen» está definida con «false» (o si está reconfigurando el paquete). A veces desea que el usuario vea la pregunta otra vez; en estos casos puede definir la marca «seen» con el valor «false» para forzar a debconf a que la muestre otra vez.
- METAGET pregunta campo
- Devuelve el valor de cualquier campo de una plantilla asociada a la pregunta («Description», por ejemplo).
- REGISTER plantilla pregunta
- Crea una nueva pregunta ligada a una plantilla. Por omisión, cada plantilla tiene una pregunta asociada con el mismo nombre. Sin embargo, se pueden asociar cualquier número de preguntas a una plantilla, permitiendo la creación de más preguntas.
- UNREGISTER pregunta
- Elimina una pregunta de la base de datos.
- PURGE
- Invoque esto en el script «postrm» al purgar el paquete. Elimina todas las preguntas de su paquete de la base de datos de debconf.
- X_LOADTEMPLATEFILE /ruta/a/plantillas [propietario]
- Esta extensión carga el fichero de plantilla especificado, en la base de datos de debconf. El propietario recibe el valor predefinido del paquete que se está configurando con debconf.
Aquí tiene un sencillo ejemplo del protocolo de debconf en acción.
INPUT medium debconf/frontend
30 question skipped
FSET debconf/frontend seen false
0 false
INPUT high debconf/frontend
0 question will be asked
GO
[ Aquí, debconf muestra al usuario una pregunta. ]
0 ok
GET no/such/question
10 no/such/question doesn't exist
GET debconf/frontend
0 Dialog
BIBLIOTECAS¶
Configurar manualmente lo necesario para poder hablar con debconf mediante el protocolo de debconf es quizá demasiado trabajo, y por ello existen algunas pequeñas bibliotecas para aliviar este arduo trabajo.
Para la programación en consola existe la biblioteca «/usr/share/debconf/confmodule», el cual puede cargar al principio del script de consola, y comunicarse con debconf con una relativa naturalidad usando las versiones en minúscula de las órdenes del protocolo de debconf, las cuales están prefijadas con «db_» (por ejemplo, «db_input» y «db_go»). Para más detalles, consulte confmodule(3).
Los programadores que usan Perl pueden usar el módulo de Perl Debconf::Client::ConfModule(3pm), y los programadores que usan Python pueden usar el módulo de Python de debconf.
El resto de este manual usará la biblioteca «/usr/share/debconf/confmodule» en los scripts de consola de ejemplo. Aquí tiene un script «config» de ejemplo que usa esa biblioteca, y que sólo plantea una pregunta:
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
db_set mi-paquete/reboot-now false
db_input high mi-paquete/reboot-now || true
db_go || true
Tenga en cuenta que el uso de «|| true» evita que el script finalice si debconf decide que no puede mostrar la pregunta, o si el usuario intenta retroceder. En estas situaciones debconf devuelve un código de salida distinto de cero, y debido a que este script usa «set -e», un código de salida sin variable de error («untrapped») haría que se cancelase.
Y aquí tiene un script «postinst» correspondiente, que usa la respuesta del usuario a la pregunta para ver si se debería reiniciar el sistema (un ejemplo algo absurdo...):
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
db_get mi-paquete/reboot-now
if [ "$RET" = true ]; then
shutdown -r now
fi
Tenga en cuenta el uso de la variable «$RET» para obtener un código de salida extendido de la orden «GET», que contiene la respuesta del usuario a la pregunta.
EL SCRIPT POSTINST¶
La última sección tenía un ejemplo de un script «postinst» que usa debconf para obtener el valor de una pregunta, y actuar en consecuencia. Existen algunas cosas que debe tener en cuenta al escribir scripts «postinst» que usan debconf:
- *
- Evite hacer preguntas en el «postinst». Por el contrario, el script «config» debería hacer preguntas mediante debconf, para que funcione la preconfiguración.
- *
- Cargue siempre «/usr/share/debconf/confmodule» al inicio de su «postinst», incluso si no va a ejecutar ninguna orden «db_*» desde el script. Es necesario para asegurar que el script «config» tenga la oportunidad de ejecutarse (para más detalles consulte «ARREGLOS»).
- *
- Evite enviar cualquier información del «postinst» a través de la salida estándar ya que puede confundir a debconf, y de todas formas, «postinst» no debería ser informativo. Enviar información a la salida de error es aceptable, de ser necesario.
- *
- Si su «postinst» inicia un demonio asegúrese de informar a debconf de que ejecute «STOP» al final, ya que de otra forma puede que debconf confunda el momento en que finaliza el script «postinst».
- *
- Haga que el script «postinst» acepte «reconfigure» como primer parámetro. Puede tratarlo al igual que «configure». Se usará en futuras versiones de debconf para informar a los script «postinst» de cuándo se reconfiguran.
OTROS SCRIPTS¶
Aparte del script «config» y «postinst», puede usar debconf en cualquier otro script de encargado de paquetes. Habitualmente, usará debconf en su «postrm» para invocar la orden «PURGE» cuando purga su paquete y así eliminar sus entradas de la base de datos debconf. (Por cierto, está configurado automáticamente mediante dh_installdebconf(1).)
Un uso más complejo de debconf sería si desea usarlo en el script «postrm» al purgar el paquete para realizar una pregunta acerca de la eliminación de algo. O puede que se vea en la necesidad de usarlo en los script «preinst» o «prerm». Todos estos usos funcionarán, aunque probablemente incluyan plantear preguntas y actuar según la respuesta en el mismo programa, en lugar de separar las dos actividades como se hace con los scripts «config» y «postint».
Tenga en cuenta que si el único uso que su paquete hace de debconf está en el script «postrm», debería comprobar que el script «postinst» del paquete carga «/usr/share/debconf/confmodule» para dar a debconf la oportunidad de cargar su fichero de plantillas en la base de datos. Así, las plantillas estarán disponibles al purgar su paquete.
También puede usar debconf con otros programas independientes. La cuestión que debe cuidar es que debconf no pretende ser, y no se debería usar, como un registro. Al fin y al cabo, esto es Unix, y los programas se configuran mediante ficheros en «/etc», y no mediante alguna difusa base de datos de debconf (que es sólo un almacén susceptible de desaparecer). Así que reflexione antes de usar debconf con un programa independiente.
Hay situaciones en las que tiene sentido, por ejemplo con el programa apt-setup, que usa debconf para realizar preguntas al usuario de una forma consistente con el resto del proceso de instalación de Debian, y así actuar según las respuestas para configurar el fichero «sources.list» de apt.
LOCALIZACIÓN¶
Debconf permite la localización de ficheros de plantilla. Esto se consigue añadiendo más campos que contienen el texto traducido. Se pueden traducir cualquiera de los campos. Por ejemplo, puede que desee traducir la descripción al español. Simplemente, cree un campo llamado «Description-es» para contener la traducción. Si no se dispone de la traducción de un campo, debconf usa el campo en inglés de forma predefinida.
Además del campo «Description» también debería traducir el campo «Choices» de una plantilla «select» o «multiselect». Asegúrese de listar las opciones traducidas en el mismo orden en el que aparecen en el campo «Choices». No necesita traducir el campo «Default» de una pregunta «select» o «multiselect», y el valor del campo aparecerá automáticamente en inglés.
Le resultará más fácil administrar las traducciones si las gestiona en ficheros separados; un fichero por traducción. En el pasado se usaban los programas debconf-getlang(1) y debconf-mergetemplate(1) para administrar los ficheros «debian/template.ll». Han quedado obsoletos por el paquete po-debconf(7), que permite administrar traducciones de debconf en ficheros «.po», al igual que cualquier otra traducción. Sus traductores le estarán agradecidos por usar este nuevo y mejorado mecanismo.
Para más detalles acerca de po-debconf, consulte su página de manual. Si usa debhelper, pasar a po-debconf es tan fácil como ejecutar la orden debconf-gettextize(1) una sola vez, y añadir una dependencia de construcción sobre po-debconf y debhelper (>= 4.1.13).
INTEGRAR LAS DIFERENTES PARTES¶
Así que tiene un script «config», un fichero de plantillas, un script «postinst» que usa debconf y así en adelante. Integrar todos estos elementos en un paquete debian no es muy difícil. Puede hacerlo a mano, o puede usar dh_installdebconf(1), el cual fusionará sus plantillas traducidas, copiará los ficheros a las ubicaciones apropiadas, y puede incluso crear la invocación a «PURGE» que debería estar en su script «postrm». Compruebe que el paquete dependa de debconf (>= 0.5) ya que las versiones anteriores no son compatibles con todo lo descrito en este manual. Y esto es todo.
Bueno, a excepción de probar, la depuración y en realidad usar debconf para cosas más interesantes que plantear unas pocas preguntas básicas. Para ello, siga leyendo...
DEPURACIÓN¶
Así que tiene un paquete que debería usar debconf, pero que no llega a funcionar. Puede que debconf no plantee la pregunta que configuró. O puede que esté ocurriendo algo más raro; está atrapado en un especie de bucle, o peor. Afortunadamente, debconf ofrece muchas facilidades para su depuración.
debconf (developer): <-- input high debconf/frontand
debconf (developer): --> 10 "debconf/frontand" doesn't exist
debconf (developer): <-- go
debconf (developer): --> 0 ok
Es bastante útil usar la interfaz readline de debconf cuando realice la depuración (según la opinión del autor), ya que las preguntas no entorpecen la labor, y la salida de depuración se puede registrar y preservar con facilidad.
- debconf-communicate
- Otra herramienta útil es el programa debconf-communicate(1). Inícielo y podrá comunicarse con debconf mediante el protocolo de debconf de forma interactiva. Es una buena forma de probar cosas inmediatamente.
- debconf-show
- Si un usuario informa de un problema puede usar debconf-show(1) para mostrar todas las preguntas del que su paquete es propietario, mostrando sus valores y si el usuario las ha visto.
- .debconfrc
Resulta que si configura un fichero «~/.debconfrc» para un usuario normal que apunta a unos ficheros «config.dat» y «template.dat» para el usuario, puede cargar plantillas y ejecutar scripts «config» cuanto desee sin permisos del usuario «root». Si desea iniciar todo con una base de datos limpia, simplemente borre los ficheros «*.dat».
Para detalles acerca de la configuración, consulte debconf.conf(5), y tenga en cuenta que «/etc/debconf.conf» es una buena plantilla para un fichero «~/.debconfrc» personal.
PROGRAMACIÓN AVANZADA CON DEBCONF¶
Manipulación de ficheros de configuración¶
Parece que muchos de vosotros queréis usar debconf para ayudar en la manipulación de los ficheros de configuración que son parte de su paquete. Puede que no exista un buen valor predefinido a incluir en un fichero de configuración, y por ello puede desear usar debconf para plantear preguntas al usuario y escribir un fichero de configuración en base a las respuestas. Puede parecer fácil, pero considere las actualizaciones, y qué hacer cuando alguien modifica el fichero de configuración que su paquete genera, cuando se usa dpkg-reconfigure, y más...
Existen varias formas de hacer esto, y la mayoría están equivocadas, generando a menudo molestos informes de fallo. Aquí tiene una de las formas correctas de hacerlo. Asume que su fichero de configuración es realmente sólo una serie de variables de entorno a definir («set»), con comentarios entre ellos, para que así pueda sólo leer el fichero para cargarlo. Si tiene un formato más complicado, leer y editar el fichero es más complicado.
Su script «config» puede tener un aspecto similar a este:
#!/bin/sh
CONFIGFILE=/etc/foo.conf
set -e
. /usr/share/debconf/confmodule
# Carga el fichero de configuración, si existe.
if [ -e $CONFIGFILE ]; then
. $CONFIGFILE || true
# Guarda los valores del fichero de
# configuración en la base de datos de debconf.
db_set mypackage/foo "$FOO"
db_set mypackage/bar "$BAR"
fi
# Plantea preguntas.
db_input medium mypackage/foo || true
db_input medium mypackage/bar || true
db_go || true
Y el script «postinst» tendrá un aspecto similar al siguiente:
#!/bin/sh
CONFIGFILE=/etc/foo.conf
set -e
. /usr/share/debconf/confmodule
# Genera el fichero de configuración, si no existe.
# Una alternativa es copiar un fichero
# de plantillas en otra ubicación. ¡ if [ ! -e $CONFIGFILE ];
then
echo "# Fichero de configuración para mi paquete " >
$CONFIGFILE
echo "FOO=" >> $CONFIGFILE
echo "BAR=" >> $CONFIGFILE
fi
# Sustituye los valores de la base de datos de debconf
# Aquí hay muchas optimizaciones posibles.
# «cp» antes de «sed» asegura que no nos
equivocamos
# con el propietario y permisos del fichero de configuración.
db_get mypackage/foo
FOO="$RET"
db_get mypackage/bar
BAR="$RET"
cp -a -f $CONFIGFILE $CONFIGFILE.tmp
# Si el administrador eliminó algunas variables pero después
las
# define («set») mediante debconf, las (re)añade al
fichero de
# configuración.
test -z "$FOO" || grep -Eq '^ *FOO=' $CONFIGFILE || \
echo "FOO=" >> $CONFIGFILE
test -z "$BAR" || grep -Eq '^ *BAR=' $CONFIGFILE || \
echo "BAR=" >> $CONFIGFILE
sed -e "s/^ *FOO=.*/FOO=\"$FOO\"/" \
-e "s/^ *BAR=.*/BAR=\"$BAR\"/" \
< $CONFIGFILE > $CONFIGFILE.tmp
mv -f $CONFIGFILE.tmp $CONFIGFILE
Considere como estos dos scripts gestionan todas las situaciones. Las preguntas se realizan por el script «config» durante una instalación nueva, y «postinst» genera un nuevo fichero de configuración. Este fichero se lee durante una actualización y reconfiguración, y los valores contenidos en él se usan para modificar los valores en la base de datos de debconf, de forma que no se pierden los cambios manuales del administrador. Las preguntas se plantean otra vez (y puede o no que se muestren). Por último, el script «postinst» sustituye los valores en el fichero de configuración, sin modificar el resto del contenido.
Permitir retroceder al usuario¶
Pocas cosas son tan frustrantes al usar un sistema como debconf que responder a una pregunta, continuar a la siguiente pantalla con una pregunta nueva, descubrir que hizo una mala elección en la pregunta anterior, querer retroceder y descubrir que no puede.
Ya que el script «config» regula el comportamiento de debconf, este no puede saltar a una pregunta anterior por si mismo, aunque puede realizar este paso con un poco de su ayuda. El primer paso es permitir que el script «config» sepa que debconf permite que el usuario pulse un botón para retroceder. Para ello, use la orden «CAPB», introduciendo «backup» como parámetro.
A continuación, después de cada orden «GO», debe comprobar si el usuario pidió retroceder (debconf devuelve un código de 30), y si es así, debe saltar a la pregunta anterior.
Existen varias formas de escribir las estructuras de control de su programa para que pueda retroceder a preguntas anteriores cuando sea necesario. Puede escribir un código complicado y confuso. O puede crear varias funciones y usar recursión. Pero quizás la forma más sencilla y limpia es crear una máquina de estado. Aquí tiene un boceto de una máquina de estado, que puede rellenar y expandir.
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
db_capb backup
STATE=1
while true; do
case "$STATE" in
1)
# Dos preguntas no relacionadas.
db_input medium my/question || true
db_input medium my/other_question || true
;;
2)
# Realiza esta pregunta sólo si
# se respondió afirmativamente
# a la primera.
db_get my/question
if [ "$RET" = "true" ]; then
db_input medium my/dep_question || true
fi
;;
*)
# El caso («case») predefinido se inicia cuando $STATE es
# mayor que el último «state» implementado,
abandonando el bucle.
# Es necesario numerar los «states» consecutivamente desde el
1
# sin espacios, ya que el «case» predefinido también
se introducirá
# si hay un espacio en la numeración.
break # exits the enclosing "while" loop
;;
esac
if db_go; then
STATE=$(($STATE + 1))
else
STATE=$(($STATE - 1))
fi
done
if [ $STATE -eq 0 ]; then
# El usuario pidió volver atrás a la primera
# pregunta. Este caso es problemático. La
# instalación regular de dpkg y apt no es capaz de
# retroceder a preguntas entre paquetes tal y como
# esto se escribe, así que esto cerraría dejando el
# paquete sin configurar - probablemente la mejor
# forma de tratar esta situación.
exit 10
fi
Tenga en cuenta que si todo lo que hace su script «config» es plantear unas pocas preguntas sin relación, no hay necesidad de una máquina de estado. Sólo plantee las preguntas, y «GO»; debconf lo hará lo mejor que pueda para mostrar todas en la misma pantalla, y así el usuario no tendrá que retroceder.
Evitar bucles infinitos¶
Debconf puede encontrar problemas si su script «config» contiene un bucle. Suponga que su consulta requiere la entrada de datos y su validación, y su repetición en caso de que no sea válida:
ok=”
do while [ ! "$ok" ];
db_input low foo/bar || true
db_go || true
db_get foo/bar
if [ "$RET" ]; then
ok=1
fi
done
Superficialmente, esto es correcto. Pero considere qué ocurre si el valor de «foo/bar» es «""» al entrar en este bucle, y si el usuario ha definido la prioridad de las preguntas a mostrar como alta, o si usa una interfaz no interactiva, de forma que en realidad no se pide ninguna entrada. El valor de «foo/bar» no se modifica mediante «db_input», fallando la prueba de validación y realizando el bucle una y otra vez...
Una forma de evitar esto es que antes de entrar en el bucle, el valor de «foo/bar» esté definido como algo que superaría la prueba en el bucle. Por ejemplo, si el valor predefinido de «foo/bar» es "1", entonces puede reiniciar («RESET») «foo/bar» antes de entrar en el bucle.
Otra forma es comprobar el código de retorno de la orden «INPUT». Si es 30, el usuario no ve la pregunta que se les plantea, y debería salir del bucle.
Escoger entre paquetes relacionados¶
A veces se pueden instalar un conjunto de paquetes relacionados, y desea consultar al usuario qué conjunto se debería usar por omisión. Ejemplos de tales conjuntos son gestores de ventanas o ficheros de diccionario ispell.
Aunque sea posible que cada paquete en el conjunto podría simplemente consultar «¿Debería ser este paquete el predefinido?», conllevaría a muchas preguntas repetitivas si se van a instalar varios paquetes. Debconf permite la presentación de una lista de todos los paquetes del conjunto, permitiendo al usuario seleccionar cuáles desea. Aquí tiene como hacerlo.
Haga que todos los paquetes en el conjunto usen una plantilla compartida (tipo «shared»). Algo como esto:
Template: shared/window-manager
Type: select
Choices: ${choices}
Description: Select the default window manager.
Select the window manager that will be started by
default when X starts.
Cada paquete debería incluir una copia de esta plantilla. También debería incluir código parecido al siguiente en su 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
Esto requiere una explicación. Llegado el momento de ejecutar su script «config», debconf ya ha analizado todas las plantillas de los paquetes que se van a instalar. Ya que el conjunto de paquetes comparten una pregunta, debconf registra este hecho en el campo «owners» (propietarios). Por una extraña coincidencia, el formato del campo «owners» es el mismo que el del campo «choices» (elecciones), una lista de valores separados por comas y espacios.
La orden «METAGET» se puede usar para obtener una lista de los propietarios y de las elecciones. Si son diferentes, se ha instalado un paquete nuevo. Use la orden «SUBST» para cambiar la lista de elecciones para que sea igual a la lista de propietarios, y plantee la pregunta.
Cuando se elimine un paquete probablemente querrá ver si ese paquete es la elección actualmente seleccionada, y si es así, querrá consultar al usuario para que seleccione un paquete diferente para reemplazarlo.
Esto se puede lograr añadiendo algo similar a lo siguiente en los scripts «prerm» de todos los paquetes relacionados (reemplazando <paquete> con el nombre del paquete).
if [ -e /usr/share/debconf/confmodule ]; then
. /usr/share/debconf/confmodule
# No declara propiedad sobre esta pregunta.
db_unregister shared/window-manager
# Comprueba que la pregunta compartida aún existe.
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 [ "<paquete>" = "$RET" ] ; then
db_fset shared/window-manager seen false
db_input high shared/window-manager || true
db_go || true
fi
# Ahora haga lo que el script «postinst» hizo
# para actualizar el enlace simbólico del gestor
# de ventanas.
fi
fi
ARREGLOS¶
A día de hoy debconf no está completamente integrado en dpkg (pero quiero cambiar esto en el futuro), y por ello actualmente se usan unos arreglos poco elegantes.
El peor de estos arreglos implica ejecutar el script «config». La forma en la que funciona ahora es ejecutar el script «config» al preconfigurar el paquete. Entonces, al ejecutar el script «postinst», inicia debconf otra vez. Debconf detecta que está en uso mediante el script «postinst», y por ello se desactiva y ejecuta el script «config». Sólo funciona si su script «postinst» carga una de las bibliotecas debconf por lo que todos los scripts «postinst» deben encargarse de ello. Esperamos cambiar esto en el futuro añadiendo la compatibilidad explicita para debconf a dpkg. El programa debconf(1) es un paso en esta dirección.
Otro arreglo relacionado es ejecutar debconf cuando un script «config», «postinst» u otro programa que lo usa se inicia. Después de todo, esperan poder comunicarse con debconf inmediatamente. La forma de lograr esto actualmente es que cuando un script carga una biblioteca de debconf (como «/usr/share/debconf/confmodule»), y debconf no está en ejecución, éste se inicia, y se ejecuta una nueva copia del script. La única diferencia notable es que necesita ubicar la línea que carga la biblioteca de debconf al principio del script o pueden ocurrir comportamientos raros. Esperamos poder cambiar en el futuro la forma en que se invoca debconf, transformándolo en un especie de demonio transitorio.
La forma en que debconf averigua qué ficheros de plantillas cargar y cuándo es también un arreglo poco elegante. Cuando los scripts «config», «preinst», y «postinst» invocan debconf, éste averiguará automáticamente dónde está el fichero de plantilla, y lo cargará. Los programas independientes que usan debconf provocarán que debconf busque ficheros de plantilla en «/usr/share/debconf/templates/progname.templates». Y si un «postrm» desea usar debconf al purgar, las plantillas no estarán disponibles a menos que debconf tenga la oportunidad de cargarlo a través de «postinst». Esto es algo confuso, pero inevitable. En el futuro, puede que algunos de estos programas sean capaces de usar debconf-loadtemplate directamente.
El comportamiento histórico de «/usr/share/debconf/confmodule» de manipular los descriptores de ficheros, configurando un descriptor de fichero 3 para comunicarse con debconf, puede causar varios tipos de problema cuando un «postinst» se comunica con debconf ya que el script finaliza la comunicación pero debconf no puede averiguar cuándo finaliza el script. Puede usar la orden «STOP» como un arreglo. En el futuro, estamos considerando hacer que la comunicación con debconf se realice a través de un «socket» o algún otro mecanismo además de la entrada y salida estándar.
Debconf define «DEBCONF_RECONFIGURE=1» antes de ejecutar scripts «postinst», de forma que un script «postinst» que deba evitar alguna operación compleja al reconfigurarse puede examinar esa variable. Este es sólo un arreglo ya que lo correcto sería introducir «$1 = "reconfigure"», pero hacerlo sin romper todos los «postinst» que usan debconf es difícil. La vía para abandonar este arreglo es animar a la gente a que escriban ficheros «postinst» que acepten «reconfigure», y una vez que todos lo hagan, empezar a introducir ese parámetro.
VÉASE TAMBIÉN¶
debconf(7) es la guía de usuario de debconf.
La especificación de debconf en las normas de Debian (debian-policy) es la definición estándar del protocolo de debconf. Puede encontrarlo en«/usr/share/doc/debian-policy/debconf_specification.txt.gz».
debconf.conf(5) contiene mucha información útil, incluyendo algo de información acerca del sistema de la base de datos.
AUTOR¶
Joey Hess <joeyh@debian.org>
TRADUCCIÓN¶
Omar Campagne Polaino <ocampagne@gmail.com>, 2010
Si encuentra un fallo en la traducción, por favor, informe de ello en la lista de traducción <debian-l10n-spanish@lists.debian.org>.