sourCEntral - mobile manpages

pdf

DEBCONF−DEVEL

NAME

debconf − Führer für Entwickler

BESCHREIBUNG

Dies ist ein Führer zum Entwickeln von Paketen, die Debconf benutzen.

Dieses Handbuch nimmt an, dass Sie als Benutzer mit Debconf vertraut sind, und dass Sie mit den Grundlagen der Konstruktion von Debian−Paketen vertraut sind.

Dieses Handbuch beginnt, indem zwei neue Dateien erklärt werden, die Debian−Paketen hinzugefügt werden, die Debconf benutzen. Dann erklärt es, wie das Debconf−Protokoll arbeitet, und verweist Sie auf einige Bibliotheken, die Ihre Programme das Protokoll sprechen lassen. Es diskutiert andere Betreuer−Skripte, in denen Debconf typischerweise benutzt wird: die Skripte postinst und postrm. Dann geht es weiter zu fortgeschritteneren Themen, wie gemeinsam benutzte Debconf−Vorlagen, Fehlersuche und einige allgemeine Techniken und Stolperfallen der Programmierung mit Debconf. Es schließt mit einer Diskussion Debconfs gegenwärtiger Einschränkungen.

DAS SKRIPT CONFIG

Debconf fügt ein zusätzliches Betreuer−Skript, das Skript config, zu der Reihe von Betreuer−Skripten, die in Debian−Paketen sein können (preinst, postinst, prerm und postrm), hinzu. Das Skript config ist verantwortlich dafür, alle für die Konfiguration des Paketes notwendigen Fragen zu stellen.

Anmerkung: Es ist ein wenig verwirrend, dass dpkg das Ausführen des Skriptes postinst eines Paketes als »Konfiguration« dieses Paketes bezeichnet, weil ein Paket, das Debconf benutzt, oft voll vor−konfiguriert ist, nämlich durch sein Skript config, bevor postinst erst ausgeführt wird. Ach ja.

Wie dem Skript postinst, werden config zwei Parameter übergeben, wenn es ausgeführt wird. Der erste sagt, welche Aktion durchgeführt wird, und der zweite ist die Version des Paketes, die gegenwärtig installiert ist. Also können Sie, wie in postinst, dpkg −−compare−versions gegen $2 benutzen, um ein bestimmtes Verhalten nur geschehen zu lassen, wenn von einer bestimmten Version des Pakets aktualisiert wird, und solche Sachen.

Das Skript config kann auf eine von drei Arten aufgerufen werden:

1

Falls ein Paket mit dpkg−preconfigure vor−konfiguriert wird, wird sein Skript config aufgerufen, und ihm werden die Parameter »configure« und die installierte Version übergeben.

2

Wenn das postinst eines Paketes ausgeführt wird, versucht Debconf auch das Skript config auszuführen, und ihm werden dieselben Parameter übergeben, die ihm übergeben werden, wenn es vor−konfiguriert wird. Dies ist notwendig, weil das Paket möglicherweise nicht vor−konfiguriert wurde, und das Skript config noch eine Chance zum Laufen braucht. Siehe HACKS für Details.

3

Falls ein Paket mit dpkg−reconfigure erneut konfiguriert wird, wird sein Skript config ausgeführt, und ihm werden die Parameter »reconfigure« und installierte Version übergeben.

Beachten Sie, da es typisch ist, ein Paket mit APT zu installieren oder zuaktualisieren, Schritte eins und zwei laufen, das Skript config also zweimal ausgeführt wird. Es sollte beim zweiten Mal nichts tun (zweimal hintereinander Fragen zu stellen ist nervig) und es sollte definitiv idempotent sein. Glücklicherweise vermeidet es Debconf standardmäßig, Fragen wiederholt zu stellen, so dass dies generell einfach zu erreichen ist.

Beachten Sie, dass das Skript config ausgeführt wird, bevor das Paket entpackt wird. Es sollte nur Befehle benutzen, die in essenziellen Paketen enthalten sind. Die einzige Abhängigkeit Ihres Paketes, die garantierterweise erfüllt ist, wenn sein Skript config läuft, ist eine (möglicherweise versionierte) Abhängigkeit von Debconf selbst.

Das Skript config sollte überhaupt nicht das Dateisystem verändern müssen. Es examiniert einfach den Zustand des Systems und stellt Fragen, und Debconf speichert die Antworten, damit später vom Skript postinst nach Ihnen gehandelt wird. Umgekehrt sollte das Skript postinst fast nie Debconf benutzen, um Fragen zu stellen, sondern sollte stattdessen nach den Antworten auf die Fragen, die das Skript config gestellt hat, handeln.

DIE DATEI TEMPLATES

Ein Paket, das Debconf benutzt, möchte möglicherweise einige Fragen stellen. Diese Fragen werden in Vorlagenform in der Datei templates gespeichert.

Wie das Skript config, wird die Datei templates in dem Teil control.tar.gz eines .deb abgelegt. Ihr Format ist ähnlich dem einer Debian−Kontroll−Datei; eine Reihe von durch Leerzeichen getrennten Instanzen, wobei jeder dieser Absätze eine Form ähnlich RFC822 hat:

Template: foo/bar
Type: string
Default: foo
Description: Dies ist ein Muster einer Zeichenkettenfrage.
Dies ist die erweiterte Beschreibung.
.
Beachten Sie dass:
− Wie in einer Paketbeschreibung Debians,
leitet ein Punkt auf seiner eigenen Zeile
einen neuen Absatz ein.
− Der meiste Text wird wortweise umbrochen,
aber zweifach eingerückter Text wird
belassen, so dass Sie dies für Listen von
Elementen benutzen können, wie diese Liste.
Seien Sie vorsichtig, weil der Text nicht
wortweise umbrochen wird, sieht er, falls
er zu breit ist, schlecht aus. Es für
kurze Elemente benutzen ist am Besten
(also ist dies ein schlechtes Beispiel).

Template: foo/baz
Type: boolean
Description: Klar genug, nein?
Dies ist eine weitere Frage, vom Booleschen Typ.

Für einige Beispiele von Vorlagendatei aus dem wahren Leben, siehe /var /lib/dpkg/info/debconf.templates, und andere Dateien auf .templates in dem Verzeichnis.

Lassen Sie uns jedes der Felder der Reihe nach ansehen:
Template (Vorlage)

Dem Namen der Vorlage, in dem Feld »Template«, wird generell der Name des Paketes vorangestellt. Danach ist der Namensraum weit offen; Sie können ein einfaches flaches Layout wie das oben benutzen, oder »Unterverzeichnisse« aufsetzen, die verwandte Fragen enthalten.

Type (Typ)

Der Typ der Vorlage bestimmt, welche Art von Oberflächen−Element dem Benutzer angezeigt wird. Die gegenwärtig unterstützten Typen sind:
string (Zeichenkette)

Resultiert in einem Eingabefeld freier Form, in das der Benutzer jegliche Zeichenkette eingeben kann.

password (Passwort)

Gibt dem Benutzer eine Eingabeaufforderung für ein Passwort aus. Benutzen Sie dies mit Vorsicht; vergegenwärtigen Sie sich, dass das Passwort, das der Benutzer eingibt, in Debconfs Datenbank geschrieben wird. Sie sollten diesen Wert möglicherweise aus der Datenbank säubern, sobald dies möglich ist.

boolean (Boolesch)

Eine Auswahl »wahr/falsch« (true/false).

select (Auswahl)

Eine Auswahl aus einer Anzahl von Werten. Die Auswahlen müssen in einem »Choices« benannten Feld angegeben werden. Trennen Sie die möglichen Werte mit Komma und Leerzeichen, wie hier:
Choices: Ja, Nein, Vielleicht

multiselect (Mehrfachauswahl)

Wie der Datentyp select, außer dass der Benutzer jegliche Anzahl von Elementen aus der Auswahlliste auswählen kann (oder gar keins).

note (Anmerkung)

Statt per se eine Frage zu sein, gibt dieser Datentyp eine Anmerkung an, die dem Benutzer angezeigt werden kann. Er sollt nur für wichtige Anmerkungen benutzt werden, die der Benutzer wirklich sehen sollte, weil Debconf durch große Schmerzen geht, um sicherzustellen, dass der Benutzer sie sieht; die Installation anhalten, dass der Benutzer eine Taste drückt. Es ist am Besten, dies nur für Warnungen über sehr ernsthafte Probleme zu benutzen, und oft ist der Datentyp »error« der passendere.

error (Fehler)

Dieser Datentyp wird für Fehlermeldungen benutzt, so wie Fehler bei der Eingabe−Validierung. Debconf zeigt eine Frage dieses Typs selbst dann, wenn die Priorität zu hoch ist oder der Benutzer sie bereits gesehen hat.

title (Titel)

Dieser Datentyp wird für Titel benutzt, die mit dem Befehl SETTITLE gesetzt werden.

text (Text)

Dieser Datentyp kann für Textfragmente benutzt werden, zum Beispiel Labels, die aus kosmetischen Gründen in der Anzeige mancher Frondends benutzt werden können. Andere Benutzerschnittstellen benutzen ihn überhaupt nicht. Es gibt noch keinen Anlass diesen Datentyp zu benutzen, weil keine Benutzerschnittstelle ihn gut unterstützt. Er mag in der Zukunft sogar entfernt werden.

Default (Vorgabe)

Das Feld »Default« sagt Debconf, was der Vorgabe−Wert sein sollte. Für den Datentyp multiselect kann es eine durch Komma und Leerzeichen getrennte Liste von Auswahlen sein, ähnlich dem Feld »Choices«. Für den Datentyp select sollte es eine der Auswahlmöglichkeiten sein. Für den Booleschen Datentyp ist es »true« oder »false«, während es bei einer Zeichenkette alles sein kann, und für Passwörter ignoriert wird.

Machen Sie nicht den Fehler zu denken, dass das Feld »Default« den »Wert« der Frage enthält, oder dass es benutzt werden kann, um den Wert der Frage zu ändern. Es tut dies nicht, und kann es nicht, es liefert lediglich einen Vorgabe−Wert, wenn die Frage das erste Mal angezeigt wird. Um eine Vorgabe zu liefern, die sich im Vorbeigehen ändert, müssten Sie den Befehl SET benutzen, um den Wert einer Frage zu ändern.

Description (Beschreibung)

Das Feld »Description« hat, wie die Beschreibung eines Debian−Paketes, zwei Teile: Eine Kurzbeschreibung und eine erweiterte Beschreibung. Beachten Sie, dass einige von Debconfs Benutzerschnittstellen die lange Beschreibung nicht anzeigen, oder sie nur anzeigen, falls der Benutzer um Hilfe bittet. Also sollte die Kurzbeschreibung für sich alleine stehen können.

Falls Sie sich keine lange Beschreibung ausdenken können, dann denken Sie zuerst weiter nach. Schreiben Sie auf debian−devel. Bitten Sie um Hilfe. Besuchen Sie ein Schriftsteller−Seminar! Diese erweiterte Beschreibung ist wichtig. Falls Sie nach allem immer noch nichts haben, lassen Sie sie leer. Es gibt keinen Anlass die Kurzbeschreibung zu kopieren.

Der Text in der erweiterten Beschreibung wird wortweise umbrochen, solange ihm nicht zusätzlicher Leerraum vorangestellt wird (über das eine erforderliche Leerzeichen hinaus). Sie können den Text auf getrennte Absätze verteilen, indem Sie » .« (Leerzeichen Punkt) auf eine eigene Linie zwischen diesen setzen.

FRAGEN

Eine Frage ist eine instanziierte Vorlage. Indem Sie Debconf bitten, eine Frage anzuzeigen, kann Ihr Skript config mit dem Benutzer interagieren. Wenn Debconf eine Vorlagendatei lädt (dies passiert wann immer ein Skript config oder postinst ausgeführt wird, instanziiert es automatisch aus jeder Vorlage eine Frage. Es ist tatsächlich möglich, aus derselben Vorlage mehrere unabhängige Fragen zu instanziieren (indem man den Befehl REGISTER benutzt), aber das ist selten notwendig. Vorlagen sind statische Daten, die aus der Vorlagendatei kommen, während Fragen benutzt werden, um dynamische Daten, wie der aktuelle Wert der Frage, ob der Benutzer die Frage gesehen hat, und so weiter, zu speichern. Behalten Sie die Unterscheidung zwischen einer Vorlage und einer Frage im Sinne, aber sorgen Sie sich nicht zu sehr darum.

GETEILTE VORLAGEN

Es ist tatsächlich möglich, eine Vorlage und eine Frage zu haben, die unter einer Reihe von Paketen geteilt werden. Alle Pakete müssen in ihren Vorlagedateien eine identische Kopie der Vorlage liefern. Dies kann nützlich sein, falls ein Haufen von Paketen dieselbe Frage stellen muss, und Sie den Benutzer damit nur einmal belästigen wollen. Geteilte Vorlagen werden generell in Debconfs Vorlagennamensraum in dem Pseudo−Verzeichnis »shared/« eingerichtet.

DAS DEBCONF−PROTOKOLL

Die Skripte config können unter Benutzung des Debconf−Protokolles mit Debconf kommunizieren. Dies ist ein einfaches zeilen−orientiertes Protokoll, ähnlich gängigen Internetprotokollen, so wie SMTP. Das Skript config schickt Debconf einen Befehl, indem es den Befehl auf die Standardausgabe schreibt. Dann kann es Debconfs Antwort von der Standardeingabe lesen.

Debconfs Antwort kann auf zwei Teile aufgeteilt sein: Einen nummerischen Ergebniskode (das erste Wort der Antwort), und einen optionalen erweiterten Ergebniskode (der Rest der Antwort). Der nummerische Kode benutzt 0, um Erfolg anzuzeigen, und andere Nummern, um verschiedene Arten von Fehlschlägen anzuzeigen. Für die vollen Details siehe die Tabelle im Dokument Debconf−Spezifikation bei den Debian−Richtlinien (policy).

Der erweiterte Rückgabewert ist generell Frei−Form und unspezifiziert, so dass Sie ihn generell ignorieren sollten, und sicherlich nicht versuchen sollten, ihn in einem Programm zu analysieren, um herauszuarbeiten, was Debconf tut. Die Ausnahme sind Befehle wie GET, was veranlasst, einen Wert in dem erweiterten Rückgabewert zurückzugeben.

Generell wollen Sie eine sprach−spezifische Bibliothek benutzen, die die Ecken und Kanten dessen behandelt, diese Verbindungen mit Debconf einzurichten und mit ihm zu kommunizieren.

Für soweit sind hier die Befehle in dem Protokoll. Dies ist nicht die maßgebliche Definition, siehe hierzu das Dokument der Debconf−Spezifikation bei den Debian−Richtlinien.
VERSION
nummer

Generell brauchen Sie diesen Befehl nicht zu benutzen. Er tauscht mit Debconf die benutzte Versionsnummer des Protokolles aus. Die aktuelle Protokoll−Version ist 2.0, und Versionen in der 2.x Serie werden rückwärts−kompatibel sein. Sie können die Nummer der Protokoll−Version angeben, die Sie sprechen, und Debconf gibt die Protokoll−Version, die es spricht, in dem erweiterten Ergebniskode zurück. Falls die Version, die Sie angeben, zu niedrig ist, antwortet Debconf mit dem nummerischen Kode 30.

CAPB fähigkeiten

Generell brauchen Sie diesen Befehl nicht zu benutzen. Er tauscht mit Debconf eine Liste unterstützter Fähigkeiten aus. Fähigkeiten, die sowohl Debconf und Sie unterstützen, werden benutzt, und Debconf antwortet mit allen Fähigkeiten, die es unterstützt.

Falls »escape« unter Ihren Fähigkeiten zu finden ist, erwartet Debconf, dass in den Befehlen, die Sie ihm schicken, Rückwärtsschrägstriche und Zeilenumbrüche geschützt sind (respektive als \\ und \n), und es schützt im Gegenzug Rückwärtsschrägstriche und Zeilenumbrüche in seinen Antworten. Die kann zum Beispiel benutzt werden, um mehrzeilige Zeichenketten zu Vorlagen zu ersetzen, oder bei der Benutzung von METAGET mehrzeilige erweiterte Beschreibungen verlässlich zu bekommen. In diesem Modus, müssen Sie Texteingaben selbst schützen (Sie können als Hilfe debconf−escape(1) benutzen, falls Sie wollen), aber die confmodule−Bibliotheken entfernen für Sie den Schutz in Antworten.

TITLE zeichenkette

Dies setzt den Titel, den Debconf dem Benutzer anzeigt. Sie müssen diesen Befehl selten benutzen, weil Debconf automatisch einen Titel basierend auf dem Namen Ihres Paketes.

SETTITLE frage

Dies setzt den Titel auf die Kurzbeschreibung der Vorlage für die angegebene Frage. Die Vorlage sollte vom Typ title sein. Der Vorteil, den dies gegenüber dem Befehl TITLE hat, ist, dass es erlaubt, dass Titel an selben Stelle wie der Rest der Debconf−Fragen gespeichert werden, und dass es erlaubt, dass sie übersetzt werden.

INPUT priorität frage

Bitte Debconf, die Anzeige einer Frage an den Benutzer vorzubereiten. Die Frage wird solange nicht tatsächlich angezeigt, bis der Befehl GO gegeben wird; dies erlaubt es, mehrere INPUT−Befehle in Serie zu geben, um eine Reihe von Fragen aufzubauen, die alle auf einem einzelnen Bildschirm gestellt werden könnten.

Das Feld Priorität sagt Debconf, wie wichtig es ist, dass diese Frage dem Benutzer angezeigt wird. Die Prioritäts−Werte sind:
niedrig (low)

Sehr triviale Elemente, die Vorgaben haben, die in der großen Mehrheit der Fälle funktionieren; nur Kontroll−Freaks sehen diese.

medium

Normale Elemente, die vernünftige Vorgaben haben.

hoch (high)

Elemente, die keine vernünftigen Vorgaben haben.

kritisch (critical)

Elemente, die möglicherweise ohne Intervention des Benutzers die Systemintegrität stören.

Debconf entscheidet, ob die Frage tatsächlich angezeigt wird, basierend auf seiner Priorität, und ob der Benutzer sie schon gesehen hat, und welche Benutzerschnittstelle benutzt wird. Falls die Frage nicht angezeigt wird, antwortet Debconf mit Kode 30.

GO

Lässt Debconf die angesammelte Reihe von Fragen (aus den INPUT−Befehlen) dem Benutzer anzeigen.

Falls die Fähigkeit backup unterstützt wird, und der Benutzer anzeigt, dass er einen Schritt zurückgehen will, antwortet Debconf mit Kode 30.

CLEAR

Löscht die angesammelte Reihe von Fragen (aus den INPUT−Befehlen) ohne sie anzuzeigen.

BEGINBLOCK
ENDBLOCK

Einige Debconf Benutzerschnittstellen können eine Anzahl von Fragen dem Benutzer auf einmal anzeigen. Vielleicht kann zukünftig sogar eine Benutzerschnittstelle diese Fragen auf dem Bildschirm in Blöcke gruppieren. BEGINBLOCK und ENDBLOCK können um eine Reihe von INPUT−Befehlen platziert werden, um Blöcke von Fragen anzuzeigen (und Blöcke können sogar geschachtelt werden). Weil noch keine Debconf−Benutzerschnittstelle so fortgeschritten ist, werden diese Befehle jetzt ignoriert.

STOP

Dieser Befehl sagt Debconf, dass Sie fertig damit sind, mit ihm zu reden. Oft kann Debconf die Beendigung Ihres Programmes erkennen, und dieser Befehl ist nicht notwendig.

GET frage

Nach der Benutzung von INPUT und GO, um eine Frage anzuzeigen, können Sie diesen Befehl benutzen, um den Wert zu erhalten, den der Benutzer eingegeben hat. Der Wert wird in dem erweiterten Ergebniskode zurückgegeben.

SET frage wert

Dies setzt den Wert einer Frage, und es kann benutzt werden, um die Vorgabe zu überstimmen, mit etwas, das Ihr Programm im Vorbeigehen berechnet.

RESET frage

Dies setzt die Frage wieder auf ihren Vorgabe−Wert (wie er in dem Feld »Default« ihrer Vorlage angegeben ist).

SUBST frage schlüssel wert

Fragen können in ihren Feldern »Description« und »Choices« Ersetzungen eingebettet haben (die Benutzung von Ersetzungen in »Choices«−Feldern ist allerdings ein wenig ein Hack; ein besserer Mechanismus wird gelegentlich entwickelt). Diese Ersetzungen sehen aus wie »${schlüssel}«. Wenn die Frage angezeigt wird, werden die Ersetzungen mit ihren Werten gefüllt. Dieser Befehl kann benutzt werden, um den Wert einer Ersetzung zu setzen. Dies ist nützlich, falls Sie dem Benutzer eine Meldung anzeigen müssen, die Sie nicht fest in der Vorlagen−Datei kodieren können.

Versuchen Sie nicht, SUBST zu benutzen, um den Vorgabe−Wert einer Frage zu ändern; es wird nicht funktionieren, da es für diesen Zweck explizit einen Befehl SET gibt.

FGET frage flag

Fragen können Flags assoziiert werden. Die Flags können die Werte »true« oder »false« haben. Dieser Befehl gibt den Wert eines Flags zurück.

FSET frage flag wert

Dies setzt den Wert eines Flags einer Frage. Der Wert muss entweder »true« oder »false« sein.

Ein gängiges Flag ist das Flag »seen«. Es ist normalerweise nur gesetzt, falls ein Benutzer eine Frage bereits gesehen hat. Debconf zeigt Benutzern für gewöhnlich nur Fragen an, falls sie das Flag »seen« auf »false« haben (oder falls es ein Paket erneut konfiguriert. Manchmal wollen Sie, dass der Benutzer eine Frage erneut sieht −− in diesen Fällen können Sie das Flag »seen« auf »false« setzen, um von Debconf zu erzwingen, dass es die Frage erneut anzeigt.

METAGET frage feld

Dies gibt den Wert eines jeglichen Felds der einer Frage zugeordneten Vorlage (zum Beispiel die Beschreibung).

REGISTER vorlage frage

Dies erzeugt eine neue Frage, die an eine Vorlage gebunden ist. Standardmäßig hat jede Vorlage eine zugeordnete Frage mit demselben Namen. Jedoch kann wirklich jede Anzahl Fragen mit einer Vorlage assoziiert sein, und dies lässt Sie mehr solcher Fragen erzeugen.

UNREGISTER frage

Die entfernt eine Frage aus der Datenbank.

PURGE

Rufen Sie dies in Ihrem postrm auf, wenn Ihr Paket vollständig entfernt wird. Es entfernt alle Fragen Ihres Paketes aus Debconfs Datenbank.

X_LOADTEMPLATEFILE /pfad/zu/templates [eigentümer]

Diese Erweiterung lädt die angegebene Vorlage−Datei in Debconfs Datenbank. Der Eigentümer ist standardmäßig das Paket, das mit Debconf konfiguriert wird.

Hier ist ein einfaches Beispiel des Debconf−Protokolles in Aktion.

INPUT medium debconf/frontend
30 question skipped
FSET debconf/frontend seen false
0 false
INPUT high debconf/frontend
0 question will be asked
GO
[ Hier zeigt Debconf dem Benutzer eine Frage an. ]
0 ok
GET no/such/question
10 no/such/question doesn’t exist
GET debconf/frontend
0 Dialog

BIBLIOTHEKEN

Die Dinge von Hand aufsetzen, so dass Sie mit Debconf reden können, und das Debconf−Protokoll sprechen ist ein wenig zu viel Arbeit, also existieren einige schlanke Bibliotheken, um diese kleinere Schinderei zu erleichtern.

Für Shell−Programmierung gibt es die Bibliothek /usr/share/debconf /confmodule, die Sie am Anfang eines Shell−Skriptes einlesen, und mit Debconf auf ziemlich natürliche Art reden können, indem Sie klein−buchstabige Versionen der Befehle des Debconf−Protokolles benutzen, denen »db_« vorangestellt ist (zB »db_input« und »db_go«). Für Details siehe confmodule(3).

Perl−Programmierer können das Perl−Modul Debconf::Client:: ConfModule(3pm), und Python−Programmierer können das Python−Modul debconf benutzen.

Der Rest dieses Handbuches benutzt die Bibliothek /usr/share/debconf /confmodule in Beispiel−Shell−Skripten. Hier ist ein Beispiel−Skript für config, das diese Bibliothek benutzt und einfach eine Frage stellt:

#!/bin/sh
set −e
. /usr/share/debconf/confmodule
db_set meinpaket/reboot−now false
db_input high meinpaket/reboot−now || true
db_go || true

Bemerken Sie den Gebrauch von »|| true«, um zu vermeiden, dass sich das Skript vorzeitig beendet, falls Debconf entscheidet, dass es eine Frage nicht anzeigen kann, oder der Benutzer versucht zurückzugehen. In diesen Situationen gibt Debconf einen Rückgabewert ungleich null zurück, und weil dies Shell−Skript mit »set −e« beginnt, würde es ein nicht−abgefangener Rückgabewert abbrechen lassen.

Und hier ist ein entsprechendes Skript postinst, das die Antwort des Benutzers auf die Frage benutzt, um zu sehen, ob das System neu gestartet werden sollte (ein eher absurdes Beispiel ...):

#!/bin/sh
set −e
. /usr/share/debconf/confmodule
db_get meinpaket/reboot−now
if [ "$RET" = true ]; then
shutdown −r now
fi

Bemerken Sie den Gebrauch der Variablen $RET, um den erweiterten Rückgabewert des Befehls GET zu erhalten, die die Antwort des Benutzers auf die Frage enthält.

DAS SCRIPT POSTINST

Der letzte Abschnitt enthielt ein Beispiel eines Skriptes postinst, das Debconf benutzt, um den Wert einer Frage zu erhalten, und danach zu handeln. Hier nun einige Dinge, die man im Sinne behalten sollte, wenn man postinst−Skripte schreibt, die Debconf benutzen:

*

Vermeiden Sie es, im postinst Fragen zu stellen. Stattdessen sollte das Skript config Fragen unter Benutzung von Debconf stellen, so dass die Vor−Konfiguration funktioniert.

*

Lesen Sie immer /usr/share/debconf/confmodule am Beginn Ihres postinst ein, selbst falls Sie in ihm keine Befehle db_* ausführen. Dies ist erforderlich, um sicherzustellen, dass das Skript config die Chance erhält zu laufen (siehe HACKS für Details).

*

Vermeiden Sie, irgendwas auf die Standardausgabe auszugeben, weil das Debconf verwirren kann, und postinst sollte ohnehin nicht wortreich sein. Ausgabe auf die Standardfehlerausgabe ist in Ordnung, falls Sie müssen.

*

Falls Ihr postinst einen Dämon startet, stellen Sie sicher, dass Sie Debconf am Ende ein STOP geben, weil Debconf sonst darüber, wann Ihr postinst zu Ende ist, ein wenig verwirrt werden kann.

*

Lassen Sie Ihr Skript postinst einen ersten Parameter »reconfigure« akzeptieren. Es kann ihn genau wie »configure« behandeln. Dies wird in einer späteren Version von Debconf benutzt werden, um postinsts wissen zu lassen, dass sie erneut konfiguriert werden.

ANDERE SKRIPTE

Neben den Skripten config und postinst, können Sie Debconf in jedem der anderen Betreuerskripten benutzen. Am gängigsten werden Sie Debconf in Ihrem postrm benutzen, um den Befehl PURGE aufzurufen, wenn Ihr Paket vollständig entfernt wird, um seine Einträge aus der Debconf−Datenbank zu säubern. (Dies wird übrigens automatisch für Sie von dh_installdebconf(1) eingerichtet.)

Ein umfassenderer Gebrauch von Debconf wäre es, falls Sie es im postrm benutzen wollten, wenn Ihr Paket vollständig entfernt wird, um eine Frage zu stellen, ob etwas gelöscht werden soll. Oder vielleicht finden Sie, dass Sie es aus irgendeinem Grund in Ihrem preinst oder prerm benutzen müssen. Alle diese Anwendungen werden funktionieren, obwohl sie es möglicherweise mit sich ziehen, in demselben Programm Fragen zu stellen und nach den Antworten zu handeln, statt diese beiden Aktivitäten zu trennen, wie es in den Skripten config und postinst geschieht.

Beachten Sie, dass falls der einzige Gebrauch von Debconf Ihres Paketes im postrm ist, Sie das postinst Ihres Paketes /usr/share/debconf- /confmodule einlesen lassen sollten, um Debconf die Chance zu geben, Ihre Vorlagendatei in seine Datenbank einzulesen. Dann werden die Vorlagen verfügbar sein, wenn Ihr Paket vollständig entfernt wird.

Sie können Debconf auch in anderen, alleinstehenden Programmen benutzen. Das Problem, auf das man hier aufpassen muss, dass Debconf nicht als eine Registrierung ausgelegt ist, und als solche nicht verwendet werden darf. Dies ist immer noch Unix, und Programme werden durch Dateien in /etc konfiguriert, nicht von irgendeiner nebulösen Debconf−Datenbank (das ist ohnehin nur ein Zwischenspeicher und kann weggeblasen werden). Also denken Sie lange und scharf nach, bevor Sie Debconf in einem alleinstehenden Programm verwenden.

Es gibt Fälle, wo es Sinn ergeben kann, wie in dem Programm apt−setup, das Debconf benutzt, das den Benutzer in einer Weise befragt, die konsistent mit dem Rest von Debians Installationsprozess ist, und das unmittelbar nach seinen Antworten handelt, um APTs sources.list einzurichten.

LOKALISIERUNG

Debconf unterstützt die Lokalisierung von Vorlage−Dateien. Dies wird durch das Hinzufügen weiterer Felder erreicht, die übersetzten Text enthalten. Jedes der Felder kann übersetzt werden. Zum Beispiel könnten Sie die Beschreibung ins Spanische übersetzen wollen. Machen Sie einfach ein »Description−es« benanntes Feld, welches die Übersetzung enthält. Falls ein übersetztes Feld nicht verfügbar ist, greift Debconf auf das normale englische Feld zurück.

Neben dem Feld »Description« sollten Sie das Feld »Choices« einer (Mehrfach−) Auswahl−Vorlage übersetzen. Stellen Sie sicher, dass Sie die übersetzten Optionen in derselben Reihenfolge auflisten, wie Sie in dem Hauptfeld »Choices« erscheinen. Sie brauchen nicht das Feld »Default« einer (Mehrfach−) Auswahl−Frage zu übersetzen, und der Wert der Frage wird automatisch in Englisch zurückgegeben.

Sie werden es einfacher finden, Übersetzungen zu verwalten, falls Sie sie in getrennten Dateien halten; eine Datei pro Übersetzung. In der Vergangenheit wurden die Programme debconf−getlang(1) und debconf−mergetemplate(1) benutzt, um Dateien nach debian/template.ll zu verwalten. Dies wurde durch das Paket po−debconf ersetzt, welches Sie mit Debconf−Übersetzungen in .po−Dateien agieren lässt, genauso wie mit anderen Übersetzungen. Ihre Übersetzer werden Ihnen den Gebrauch dieses neuen, verbesserten Mechanismus danken.

Für die Details zu po−debconf, siehe seine Datei README. Falls Sie debhelper benutzen, ist das Konvertieren nach po−debconf ein einfaches einmaliges Ausführen des Befehls debconf−gettextize(1) und das Hinzufügen einer Bauzeit−Abhängigkeit auf po−debconf und debhelper (>= 4.1.13).

DAS ALLES ZUSAMMENSETZEN

Nun haben Sie also ein Skript config, eine Datei templates, ein Skript postinst, das Debconf benutzt und so weiter. Diese Teile zu einem Debian−Paket zusammenzusetzen ist nicht schwer. Sie können es von Hand machen, oder Sie können dh_installdebconf(1) benutzen, welches Ihre übersetzten Vorlagen zusammenfügt, für Sie die Dateien an die richtigen Stellen kopiert, und das sogar den Aufruf von PURGE generieren kann, der in Ihren Skript postrm stehen sollte. Stellen Sie sicher, dass Ihr Paket von debconf (>= 0.5) abhängt, da frühere Versionen nicht mit allem in diesem Handbuch beschriebenen kompatibel waren. Und Sie sind durch.

Nun, außer was das Testen, die Fehlersuche und das tatsächliche Benutzen von Debconf für interessantere Dinge, als ein Paar grundlegende Fragen zu stellen, angeht. Lesen Sie für diese Dinge weiter.

FEHLERSUCHE

Sie haben nun also ein Paket, welches Debconf benutzen soll, aber es funktioniert nicht so richtig. Vielleicht stellt Debconf einfach nicht die Fragen, die Sie eingerichtet haben. Oder vielleicht geschieht etwas verrückteres; es hängt in irgendeiner Endlosschleife, oder schlimmer. Glücklicherweise hat Debconf viele Fähigkeiten zur Fehlersuche.
DEBCONF_DEBUG

Die erste Sache, nach der zu greifen ist, ist die Umgebungsvariable DEBCONF_DEBUG. Falls Sie DEBCONF_DEBUG=developer setzen und exportieren, gibt Debconf auf der Standardfehlerausgabe einen Abzug des Debconf−Protokolles aus, während Ihr Programm läuft. Er sieht ungefähr so aus −− der Tippfehler ist klar:

debconf (developer): <−− input high debconf/frontand
debconf (developer): −−> 10 "debconf/frontand" doesn’t exist
debconf (developer): <−− go
debconf (developer): −−> 0 ok

Es ist ziemlich nützlich (nach der Meinung des Autors), Debconfs Benutzerschnittstelle readline zu benutzen, während Sie auf der Fehlersuche sind, da die Fragen nicht im Weg sind, und alle Ausgabe zur Fehlersuche einfach aufbewahrt und protokolliert werden kann.

debconf−communicate

Ein weiteres nützliches Werkzeug ist das Programm debconf−communicate(1). Starten Sie es, und Sie können interaktiv das rohe Debconf−Protokoll mit Debconf sprechen. Dies ist großartig, um Sachen im Vorbeigehen auszuprobieren.

debconf−show

Falls ein Benutzer von einem Problem berichtet, kann debconf−show(1) benutzt werden, um einen Abzug aller Fragen, die Ihr Paket besitzt, zu erstellen, unter Anzeige ihrer Werte, und ob der Benutzer sie gesehen hat.

.debconfrc

Um den oft ermüdenden Zyklus Bauen/Installieren/Fehlersuchen zu vermeiden, kann es nützlich sein, Ihre Vorlagen mit debconf−loadtemplate(1) zu laden, und Ihr Skript config von Hand mit dem Befehl debconf(1) auszuführen. Jedoch müssen Sie dies immer noch als root machen, richtig? Nicht so gut. Und idealerweise würden Sie gerne sehen, wie eine frische Installation Ihres Paketes aussieht, mit einer sauberen Debconf−Datenbank.

Es stellt sich heraus, dass falls Sie eine Datei ~/.debconfrc für einen normalen Benutzer aufsetzen, die auf persönliche config.dat und template.dat für diesen Benutzer verweist, Sie nach Belieben Vorlagen laden und config−Skripte ausführen können, ohne irgendeinen root−Zugriff. Falls Sie mit einer sauberen Datenbank von Vorne beginnen möchten, löschen Sie einfach die Dateien *.dat.

Für Details, dies aufzusetzen, siehe debconf.conf(5) und beachten Sie dass /etc/debconf.conf eine gute Vorlage für eine persönliche Datei ~/.debconfrc abgibt.

FORTGESCHRITTENES PROGRAMMIEREN MIT DEBCONF

Handhabung von Konfigurationsdateien
Viele von Ihnen scheinen Debconf benutzen zu wollen, um bei der Verwaltung von Konfigurationsdateien zu helfen, die Teil Ihres Paketes sind. Vielleicht gibt es keine gute Voreinstellung, die man mit einem Conffile ausliefern könnte, und deshalb wollen Sie Debconf benutzen, um den Benutzer zu fragen, und basierend auf seinen Antworten eine Konfigurationsdatei schreiben. Das scheint einfach genug zu erledigen, aber dann denken Sie an Aktualisierungen, und was zu tun ist, wenn jemand die von Ihnen generierte Konfigurationsdatei verändert, und dpkg−reconfigure, und ...

Es gibt viele Arten dies zu machen, und die meisten von ihnen sind falsch und werden Ihnen oft verärgerte Fehlerberichte einbringen. Hier gibt es einen richtigen Weg, es zu machen. Er nimmt an, dass Ihre Konfigurationsdatei wirklich nur eine Reihe von gesetzten Shell−Variablen ist, mit Kommentaren dazwischen, und Sie deshalb die Datei nur einzulesen brauchen, um sie zu »laden«. Falls Sie ein komplizierteres Format haben, wird es ein wenig verzwickter, sie zu lesen (und zu schreiben).

Ihr Skript config sollte ungefähr so aussehen:

#!/bin/sh
CONFIGFILE=/etc/foo.conf
set −e
. /usr/share/debconf/confmodule

# Laden Sie die Konfigurationsdatei,
# falls sie existiert.
if [ −e $CONFIGFILE ]; then
. $CONFIGFILE || true

# Speichern Sie Werte aus der
# Konfigurationsdatei in die
# Debconf−Datenbank.
db_set mypackage/foo "$FOO"
db_set mypackage/bar "$BAR"
fi

# Stellen Sie Fragen.
db_input medium mypackage/foo || true
db_input medium mypackage/bar || true
db_go || true

Und postinst sollte ungefähr so aussehen:

#!/bin/sh
CONFIGFILE=/etc/foo.conf
set −e
. /usr/share/debconf/confmodule

# Generieren Sie die Konfigurationsdatei,
# falls sie nicht existiert. Eine
# Alternative ist, von irgendwoanders eine
# Vorlagen−Datei zu kopieren.
if [ ! −e $CONFIGFILE ]; then
echo "# Config file for my package" > $CONFIGFILE
echo "FOO=" >> $CONFIGFILE
echo "BAR=" >> $CONFIGFILE
fi

# Setzen Sie die Werte aus den Debconf−DB ein.
# Hier gibt es möglicherweise offensichtliche
# Optimierungen. Das cp vor dem sed stellt
# sicher, dass wir nicht die Besitzer und
# Rechte der Konfigurationsdatei
# durcheinanderbringen. db_get mypackage/foo
FOO="$RET"
db_get mypackage/bar
BAR="$RET"
cp −a −f $CONFIGFILE $CONFIGFILE.tmp

# Falls der Administrator einige Variablen gelöscht
# oder auskommentiert, aber sie dann über Debconf
# gesetzt hat, fügen Sie sie dem Conffile wieder hinzu.
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

Bedenken Sie, wie diese beiden Skripte alle Fälle handhaben. Bei einer frischen Installation stellt das Skript config die Fragen, und postinst generiert eine neue Konfigurationsdatei. Bei Aktualisierungen und erneutem Konfigurieren wird die Konfigurationsdatei eingelesen, und die Werte darin werden benutzt, um die Werte in der Debconf−Datenbank zu ändern, so dass händische Änderungen des Administrators nicht verloren gehen. Die Fragen werden wieder gestellt (und werden möglicherweise angezeigt oder nicht angezeigt). Dann ersetzt postinst die Werte zurück in die Konfigurationsdatei, den Rest von ihr unverändert lassend.

Den Benutzer zurück gehen lassen
Few things are more frustrating when using a system like debconf than being asked a question, and answering it, then moving on to another screen with a new question on it, and realizing that hey, you made a mistake, with that last question, and you want to go back to it, and discovering that you can’t.

Since debconf is driven by your config script, it can’t jump back to a previous question on its own but with a little help from you, it can accomplish this feat. The first step is to make your config script let debconf know it is capable of handling the user pressing a back button. You use the CAPB command to do this, passing backup as a parameter.

Then after each GO command, you must test to see if the user asked to back up (debconf returns a code of 30), and if so jump back to the previous question.

Es gibt mehrere Möglichkeiten, die Kontrollstrukturen Ihres Programmes zu schreiben, so dass sie bei Bedarf zu vorhergehenden Fragen zurückspringen können. Sie können Spaghetti−Code (voller GOTOs) schreiben. Oder Sie können mehrere Funktionen erstellen und Rekursion verwenden. Aber die wahrscheinlich sauberste und leichteste Art ist die Erstellung einer Zustandsmaschine. Hier ist ein Skelett einer Zustandsmaschine, das Sie ausfüllen und erweitern können:

#!/bin/sh
set −e
. /usr/share/debconf/confmodule
db_capb backup

STATE=1
while true; do
case "$STATE" in
1)
# Two unrelated questions.
db_input medium my/question || true
db_input medium my/other_question || true
;;
2)
# Only ask this question if the
# first question was answered in
# the affirmative.
db_get my/question
if [ "$RET" = "true" ]; then
db_input medium my/dep_question || true
fi
;;
*)
# The default case catches when $STATE is greater than the
# last implemented state, and breaks out of the loop. This
# requires that states be numbered consecutively from 1
# with no gaps, as the default case will also be entered
# if there is a break in the numbering
break # exits the enclosing "while" loop ;;
esac

if db_go; then
STATE=$(($STATE + 1))
else
STATE=$(($STATE − 1))
fi
done

if [ $STATE −eq 1 ]; then
# The user has asked to back up from the first
# question. This case is problematical. Regular
# dpkg and apt package installation isn’t capable
# of backing up questions between packages as this
# is written, so this will exit leaving the package
# unconfigured − probably the best way to handle
# the situation.
exit 10
fi

Note that if all your config script does is ask a few unrelated questions, then there is no need for the state machine. Just ask them all, and GO; debconf will do its best to present them all in one screen, and the user won’t need to back up.

Verhinderung von Endlosschleifen
One gotcha with debconf comes up if you have a loop in your config script. Suppose you’re asking for input and validating it, and looping if it’s not valid:

ok=”
do while [ ! "$ok" ];
db_input low foo/bar || true
db_go || true
db_get foo/bar
if [ "$RET" ]; then
ok=1
fi
done

This looks ok at first glance. But consider what happens if the value of foo/bar is "" when this loop is entered, and the user has their priority set high, or is using a non−interactive frontend, and so they are not really asked for input. The value of foo/bar is not changed by the db_input, and so it fails the test and loops. And loops ...

One fix for this is to make sure that before the loop is entered, the value of foo/bar is set to something that will pass the test in the loop. So for example if the default value of foo/bar is "1", then you could RESET foo/bar just before entering the loop.

Another fix is to check the return code of the INPUT command. If it is 30 then the user is not being shown the question you asked them, and you should break out of the loop.

Choosing among related packages
Sometimes a set of related packages can be installed, and you want to prompt the user which of the set should be used by default. Examples of such sets are window managers, or ispell dictionary files.

While it would be possible for each package in the set to simply prompt, "Should this package be default?", this leads to a lot of repetitive questions if several of the packages are installed. It’s possible with debconf to present a list of all the packages in the set and allow the user to choose between them. Here’s how.

Make all the packages in the set use a shared template. Something like this:

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.

Jedes Paket sollte eine Kopie der Vorlage beinhalten. Dann sollte es auch Code der folgenden Art in seinem Konfigurationsskript enthalten:

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

A bit of an explanation is called for. By the time your config script runs, debconf has already read in all the templates for the packages that are being installed. Since the set of packages share a question, debconf records that fact in the owners field. By a strange coincidence, the format of the owners field is the same as that of the choices field (a comma and space delimited list of values).

The METAGET command can be used to get the list of owners and the list of choices. If they are different, then a new package has been installed. So use the SUBST command to change the list of choices to be the same as the list of owners, and ask the question.

When a package is removed, you probably want to see if that package is the currently selected choice, and if so, prompt the user to select a different package to replace it.

Dies kann erreicht werden, in dem etwas der folgenden Art in die Prerm−Skripte aller betroffenen Pakete eingefügt wird (ersetzen Sie <Paket> durch den Namen des Pakets.

if [ −e /usr/share/debconf/confmodule ]; then
. /usr/share/debconf/confmodule
# I no longer claim this question.
db_unregister shared/window−manager

# Prüfe, ob die gemeinsam benutzen Fragen noch existieren.
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 [ "<Paket>" = "$RET" ] ; then
db_fset shared/window−manage seen false
db_input high shared/window−manager || true
db_go || true
fi

# Now do whatever the postinst script did
# to update the window manager symlink.
fi
fi

HACKS

Debconf ist derzeit nicht komplett in Dpkg integriert (ich möchte dies aber zukünftig ändern) und daher werden einige schmutzige Hacks benötigt.

The worst of these involves getting the config script to run. The way that works now is the config script will be run when the package is pre−configured. Then, when the postinst script runs, it starts up debconf again. Debconf notices it is being used by the postinst script, and so it goes off and runs the config script. This can only work if your postinst loads up one of the debconf libraries though, so postinsts always have to take care to do that. We hope to address this later by adding explicit support to dpkg for debconf. The debconf(1) program is a step in this direction.

A related hack is getting debconf running when a config script, postinst, or other program that uses it starts up. After all, they expect to be able to talk to debconf right away. The way this is accomplished for now is that when such a script loads a debconf library (like /usr/share/debconf/confmodule), and debconf is not already running, it is started up, and a new copy of the script is re−execed. The only noticeable result is that you need to put the line that loads a debconf library at the very top of the script, or weird things will happen. We hope to address this later by changing how debconf is invoked, and turning it into something more like a transient daemon.

It’s rather hackish how debconf figures out what templates files to load, and when it loads them. When the config, preinst, and postinst scripts invoke debconf, it will automatically figure out where the templates file is, and load it. Standalone programs that use debconf will cause debconf to look for templates files in /usr/share/debconf/templates/progname.templates. And if a postrm wants to use debconf at purge time, the templates won’t be available unless debconf had a chance to load them in its postinst. This is messy, but rather unavoidable. In the future some of these programs may be able to use debconf−loadtemplate by hand though.

/usr/share/debconf/confmodule’s historic behavior of playing with file descriptors and setting up a fd #3 that talks to debconf, can cause all sorts of trouble when a postinst runs a daemon, since the daemon ends up talking to debconf, and debconf can’t figure out when the script terminates. The STOP command can work around this. In the future, we are considering making debconf communication happen over a socket or some other mechanism than stdio.

Debconf sets DEBCONF_RECONFIGURE=1 before running postinst scripts, so a postinst script that needs to avoid some expensive operation when reconfigured can look at that variable. This is a hack because the right thing would be to pass $1 = "reconfigure", but doing so without breaking all the postinsts that use debconf is difficult. The migration plan away from this hack is to encourage people to write postinsts that accept "reconfigure", and once they all do, begin passing that variable.

ÜBERSETZUNG

Die deutsche Übersetzung wurde 2008 von Florian Rehnisch <eixman AT gmx DOT de> und Helge Kreutzmann <debian AT helgefjell DOT de> angefertigt. Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 2 oder neuer für die Kopierbedingungen. Es gibt KEINE HAFTUNG.

SIEHE AUCH

debconf(7) ist der Benutzerleitfaden von Debconf.

Die Debconf−Spezifikation in den Debian−Richtlinien (»policy«) ist die kanonische Definition des Debconf−Protokolls. /usr/share/doc/debian−policy/debconf_specification.txt.gz

In debconf.conf(5) sind viele nützliche Informationen, darunter auch über die Backend−Datenbank.

AUTOR

Joey Hess <joeyh AT debian DOT org>

pdf