NAME
debconf - Leitfaden für EntwicklerBESCHREIBUNG
Dies ist ein Leitfaden zum Entwickeln von Paketen, die Debconf benutzen. Dieses Handbuch nimmt an, dass Sie als Benutzer mit Debconf und 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 vor der ersten Ausführung von postinst durch sein Skript config bereits voll vorkonfiguriert ist. 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 mit $2 benutzen, um ein bestimmtes Verhalten nur erfolgen zu lassen, wenn von einer bestimmten Version des Pakets aktualisiert wird und ähnliche Sachen. Das Skript config kann auf eine von drei Arten aufgerufen werden:- 1
- Falls ein Paket mit dpkg-preconfigure vorkonfiguriert 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 vorkonfiguriert 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.
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 Abschnitt control.tar.gz eines .deb abgelegt. Ihr Format ist ähnlich dem einer Debian-Control-Datei; eine Reihe von durch Leerzeichen getrennten Instanzen, wobei jeder dieser Instanzen 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
schlecht aus, falls er zu breit ist. 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 auf .templates endende Dateien 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 eine beliebige 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. Sie sollte nur für wichtige Anmerkungen benutzt werden, die der Benutzer wirklich sehen sollte, weil Debconf großen Aufwand betreibt, um sicherzustellen, dass der Benutzer sie sieht; die Installation anhält, so 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 passendere Datentyp »error«.
- 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 Beschriftungen, die aus kosmetischen Gründen in der Anzeige mancher Benutzerschnittstellen 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 Zeile 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.GEMEINSAM BENUTZTE VORLAGEN
Es ist tatsächlich möglich, eine Vorlage und eine Frage zu haben, die von einer Reihe von Paketen gemeinsam benutzt 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. Gemeinsam benutzte Vorlagen werden generell in Debconfs Vorlagennamensraum in dem Pseudo-Verzeichnis »shared/« eingerichtet.DAS DEBCONF-PROTOKOLL
Die Skripte config können unter Benutzung des Debconf-Protokolls mit Debconf kommunizieren. Dies ist ein einfaches zeilen-orientiertes Protokoll, ähnlich gängigen Internetprotokollen 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 Ergebniscode (das erste Wort der Antwort) und einen optionalen erweiterten Ergebniscode (der Rest der Antwort). Der nummerische Code 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 in den Debian-Richtlinien (policy). Der erweiterte Rückgabewert ist generell formfrei 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, die veranlassen, einen Wert in dem erweiterten Rückgabewert zurückzugeben. Im Allgemeinen ist es sinnvoll, eine sprachspezifische Bibliothek benutzen, die sich um die Details der Einrichtung von und Kommunikation über diese Verbindungen mit Debconf kümmert. Für soweit sind hier die Befehle in dem Protokoll. Dies ist nicht die maßgebliche Definition, siehe hierzu das Dokument der Debconf-Spezifikation in den Debian-Richtlinien.- VERSION Nummer
- Im Allgemeinen 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 Ergebniscode zurück. Falls die Version, die Sie angeben, zu niedrig ist, antwortet Debconf mit dem nummerischen Code 30.
- CAPB Fähigkeiten
Im Allgemeinen brauchen Sie diesen Befehl
nicht zu benutzen. Er tauscht mit Debconf eine Liste unterstützter
Fähigkeiten (getrennt durch Leerzeichen) 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.
- SETTITLE Frage
Dies setzt den Titel, den Debconf dem Benutzer
anzeigt. Hierzu wird die Kurzbeschreibung der Vorlage für die
angegebene Frage verwandt. Die Vorlage sollte vom Typ »Title«
sein. Sie müssen diesen Befehl selten benutzen, weil Debconf
automatisch einen Titel basierend auf dem Namen Ihres Paketes erstellt.
Setzen des Titel aus einer Vorlage bedeutet, dass sie am gleichen Ort wie der
Rest der Debconf-Fragen gespeichert sind und dass eine Übersetzung
erlaubt wird.
- TITLE Zeichenkette
- Dies setzt den Titel, den Debconf dem Benutzer anzeigt. Hierzu wird die angegebene Zeichenkette verwandt. Die Verwendung des Befehls »SETTITLE« wird normalerweise bevorzugt, da es die Übersetzung des Titels erlaubt.
- 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.
- 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
Code 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 derzeit 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 Ergebniscode 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 direkt 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 irgendwann einmal 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 Schalter
- Fragen können Schalter assoziiert werden. Die Schalter können die Werte »true« oder »false« haben. Dieser Befehl gibt den Wert eines Schalters zurück.
- FSET Frage Schalter Wert
Dies setzt den Wert eines Schalters einer
Frage. Der Wert muss entweder »true« oder »false«
sein.
Ein gängiger Schalter ist der Schalter »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 der
Schalter »seen« auf »false« gesetzt ist (oder
falls es ein Paket erneut konfiguriert). Manchmal wollen Sie, dass der
Benutzer eine Frage erneut sieht -- in diesen Fällen können Sie
den Schalter »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) zurück.
- 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
- Dies 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.
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 da 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 Sie im Kopf behalten sollten, wenn Sie postinst-Skripte schreiben, 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 Daemon startet, stellen Sie sicher, dass Sie Debconf am Ende ein STOP übermitteln, 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. Sie müssen hierbei aufpassen, 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 könnte entfernt 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. Es benutzt Debconf, um den Benutzer in einer Weise zu befragen, die konsistent mit dem Rest von Debians Installationsprozess ist und dann 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. Erstellen 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 auf 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 debian/template.ll zu verwalten. Dies wurde durch das Paket po-debconf(7) 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 lesen Sie seine Handbuchseite. 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 fertig. 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 dafür 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 (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_C_VALUES
Falls diese Umgebungsvariable auf
»true« gesetzt ist, wird die Benutzerschnittstelle die Werte
statt die beschreibenden Werte in Choices-C-Feldern (so vorhanden) von select-
und multiselect-Vorlagen anzeigen.
- 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 ohne
irgendeinen root-Zugriff Vorlagen laden und config-Skripte ausführen
können. 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 Upgrades, 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 die Konfigurationsdatei,
# falls sie existiert.
if [ -e $CONFIGFILE ]; then
. $CONFIGFILE || true
# Speicher Werte aus der
# Konfigurationsdatei in die
# Debconf-Datenbank.
db_set mypackage/foo "$FOO"
db_set mypackage/bar "$BAR"
fi
# Stelle 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
# Generiere 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üge 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 Upgrades 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
Es gibt wenige Dinge, die frustrierender bei der Benutzung eines Systems wie Debconf sind, als dieses: Ihnen wird eine Frage gestellt und Sie beantworten sie, dann gehen Sie zu einem neuen Bildschirm mit einer neuen Frage, und Sie merken -- hoppla, dass Sie bei der letzten Frage einen Fehler gemacht haben, und Sie wollen zu ihr zurückgehen, und Sie erkennen, dass Sie dies nicht können. Weil Debconf von Ihrem Skript config betrieben wird, kann es nicht von allein zu einer vorigen Frage zurückspringen, aber mit ein wenig Hilfe von Ihnen kann es dieses leisten. Der erste Schritt ist, dass Sie Ihr Skript config Debconf wissen lassen, dass es fähig ist, einen Druck des Benutzers auf den »Zurück«-Knopf zu handhaben. Um dies zu tun, benutzen Sie den Befehl CAPB, indem Sie »backup« als Parameter übergeben. Dann müssen Sie nach jedem Befehl »GO« testen, um zu sehen, ob der Benutzer angefordert hat, zurück zu gehen (Debconf gibt dann einen Code 30 zurück) und falls ja, müssen Sie zu der vorigen Frage zurück springen. 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
ZUSTAND=1
while true; do
case "$ZUSTAND" in
1)
# Zwei Fragen ohne Bezug zueinander.
db_input medium meine/frage || true
db_input medium meine/andere_frage || true
;;
2)
# Stelle diese Frage nur, falls die
# erste Frage positiv beantwortet
# wurde.
db_get meine/frage
if [ "$RET" = "true" ]; then
db_input medium meine/abhaengige_frage || true
fi
;;
*)
# Der Standard-Fall wird erreicht, wenn $ZUSTAND größer als
# der letzte implementierte Zustand ist und springt
# aus der Schleife heraus. Dies erfordert, dass die
# Zustände durchgehend ohne Lücken von 1 an
# nummeriert werden, weil der Standard-Fall auch erreicht
# wird, falls es eine Unterbrechung in der
# Nummerierung gibt.
break # verlässt die umschließende »while«-Schleife
;;
esac
if db_go; then
ZUSTAND=$(($ZUSTAND + 1))
else
ZUSTAND=$(($ZUSTAND - 1))
fi
done
if [ $ZUSTAND -eq 0 ]; then
# Der Benutzer hat angefordert, von der ersten
# Frage aus zurückzugehen. Dieser Fall ist
# problematisch. Die reguläre Paket-Installation
# mit dpkg und APT ist nicht fähig, zwischen
# Fragen von zwei Paketen zurückzugehen,
# zumindest, als dies geschrieben wurde, also
# wird dies beenden, wobei das Paket
# unkonfiguriert bleibt - möglicherweise
# die beste Weise, die Situation zu behandeln.
exit 10
fi Beachten Sie: Falls das Skript config nur ein Paar Fragen ohne Bezug zueinander stellt ist eine Zustandsmaschine unnötig. Stellen Sie einfach alle Fragen und sagen Sie »GO«; Debconf wird sein Bestes geben, sie alle auf einem Bildschirm anzuzeigen, und der Benutzer wird nicht zurück gehen müssen.
Verhinderung von Endlosschleifen
Ein häufiger Fehler bei Debconf tritt in Erscheinung, falls Sie eine Schleife in Ihrem Skript config haben. Angenommen, Sie fordern eine Eingabe an und prüfen sie auf ihre Gültigkeit, und gehen in eine Schleife, falls sie nicht gültig ist:ok=”
do while [ ! "$ok" ];
db_input low foo/bar || true
db_go || true
db_get foo/bar
if [ "$RET" ]; then
ok=1
fi
done Auf den ersten Blick sieht dies gut aus. Aber bedenken Sie, was passiert, falls der Wert von »foo/bar« leer (»«) ist, wenn diese Schleife betreten wird, und der Benutzer die Priorität auf »hoch« (high) gesetzt hat, oder er die nicht-interaktive Schnittstelle benutzt, und deshalb nicht wirklich um Eingabe gebeten wird. Der Wert von »foo/bar« wird von »db_input« nicht verändert, also scheitert der Test und wir bleiben in der Schleife. Und bleiben in der Schleife ... Eine Korrektur hierfür ist, sicherzustellen, dass der Wert von »foo/bar« auf etwas gesetzt wird, das den Test in der Schleife passiert, bevor die Schleife betreten wird. Falls also zum Beispiel der Standardwert von »foo/bar« »1« ist, dann könnten Sie, gerade vor dem Betreten der Schleife, »RESET« anwenden, um den Wert von »foo/bar« zurück zu setzten. Eine weitere Korrektur besteht darin, den Rückgabewert des Befehls »INPUT« zu prüfen. Falls er 30 ist, dann wird dem Benutzer die Frage, die Sie ihm gestellt haben, nicht angezeigt, und Sie sollten die Schleife verlassen.
Zwischen verwandten Paketen auswählen
Manchmal kann eine Reihe verwandter Pakete installiert sein und Sie wollen den Benutzer fragen, welches aus der Menge als Voreinstellung benutzt werden sollte. Beispiele solcher Mengen sind Fenster-Manager, oder Wörterbuch-Dateien für »ispell«. Während es möglich wäre, dass jedes Paket in der Reihe einfach fragt, »Soll dieses Paket die Voreinstellung sein?«, führt dies zu vielen sich wiederholenden Fragen, falls mehrere der Pakete installiert werden. Mit Debconf ist es möglich, eine Liste aller Pakete der Menge anzuzeigen und dem Benutzer zu erlauben, zwischen ihnen zu wählen. Hier folgt wie. Lassen Sie alle Pakete in der Menge eine gemeinsam benutzte Vorlage benutzen. Etwas wie dies: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 Dies verlangt etwas Erklärung. Zu der Zeit zu der Ihr Skript config läuft hat Debconf bereits alle Vorlagen für die Pakete, die installiert werden, eingelesen. Weil die Menge von Paketen eine Frage gemeinsam benutzt, speichert Debconf diese Tatsache in dem Eigentümer-Feld. Durch eine merkwürdige Fügung haben das Eigentümer-Feld und das Auswahlen-Feld dasselbe Format (eine durch Komma und Leerzeichen getrennte Liste von Werten). Der Befehl »METAGET« kann benutzt werden, um die Liste der Eigentümer und die Liste der Auswahlen zu erhalten. Falls Sie verschieden sind wurde ein neues Paket installiert. Also benutzen Sie den Befehl »SUBST«, um die Liste der Auswahlen so zu ändern, dass sie die selbe ist, wie die Liste der Eigentümer, und stellen die Frage. Wenn ein Paket entfernt wird, wollen Sie möglicherweise sehen, ob das Paket die gegenwärtig ausgewählte Auswahl ist, und falls ja, den Benutzer bitten, ein anderes Paket auszuwählen, um es zu ersetzen. 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
# Ich beanspruche nicht mehr diese Frage.
db_unregister shared/window-manager
# Prüfe, ob die gemeinsam benutzte Frage noch existiert.
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-manager seen false
db_input high shared/window-manager || true
db_go || true
fi
# Nun tun Sie, was immer das Skript postinst tat,
# um den symbolischen Link des Fenster-Managers
# zu aktualisieren.
fi
fi