Provided by: debconf-doc_1.5.91_all 

NUME
debconf - ghidul dezvoltatorilor
DESCRIERE
Acesta este un ghid pentru dezvoltarea de pachete care utilizează debconf.
Acest manual presupune că sunteți familiarizat cu debconf în calitate de utilizator și că sunteți
familiarizat cu elementele de bază ale construcției pachetelor debian.
Acest manual începe prin a explica două fișiere noi care sunt adăugate la pachetele debian care
utilizează debconf. Apoi explică modul în care funcționează protocolul debconf și vă indică câteva
biblioteci care vor permite programelor dvs. să utilizeze protocolul. Sunt discutate și alte scripturi de
întreținere în care debconf este utilizat în mod obișnuit: scripturile „postinst” și „postrm”. Apoi trece
la subiecte mai avansate, cum ar fi șabloanele debconf partajate, depanarea și unele tehnici și capcane
comune ale programării cu debconf. Se încheie cu o discuție despre deficiențele actuale ale debconf.
SCRIPTUL DE CONFIGURARE
Debconf adaugă un script de întreținere suplimentar, scriptul „config”, la setul de scripturi de
întreținere care pot fi în pachetele debian („postinst”, „preinst”, „postrm” și „prerm”). Scriptul config
este responsabil cu adresarea oricăror întrebări necesare pentru configurarea pachetului.
Notă: Este puțin confuz faptul că dpkg se referă la rularea scriptului „postinst” al unui pachet ca la
„configurarea” pachetului, deoarece un pachet care utilizează debconf este adesea complet pre-configurat,
prin scriptul său de configurare, înainte ca scriptul „postinst” să fie rulat vreodată. În fine!
La fel ca „postinst”, scriptul „config” primește doi parametri atunci când este rulat. Primul spune ce
acțiune este efectuată, iar al doilea este versiunea pachetului care este instalat în prezent. Astfel, la
fel ca în „postinst”, puteți utiliza dpkg --compare-versions pe $2 pentru a face ca un anumit
comportament să se întâmple numai la actualizarea de la o anumită versiune a unui pachet și alte lucruri
de acest gen.
Scriptul de configurare poate fi rulat în trei moduri:
1 Dacă un pachet este preconfigurat, cu dpkg-preconfigure, scriptul său de configurare este rulat și
i se transmit parametrii „configure” și installed-version.
2 Atunci când scriptul „postinst” al unui pachet este rulat, debconf va încerca să ruleze și
scriptul „config”, iar acestuia i se vor pasa aceiași parametri care i-au fost pasați atunci când
a fost preconfigurat. Acest lucru este necesar deoarece este posibil ca pachetul să nu fi fost
preconfigurat, iar scriptul „config” trebuie să aibă în continuare șansa de a se executa.
Consultați secțiunea TRUCURI pentru detalii.
3 Dacă un pachet este reconfigurat, cu dpkg-reconfigure, scriptul său „config” este rulat și i se
transmit parametrii „reconfigure” și installed-version.
Rețineți că, deoarece o instalare sau o actualizare tipică a unui pachet utilizând apt execută pașii 1 și
2, scriptul „config” va fi de obicei executat de două ori. Acesta nu ar trebui să facă nimic a doua oară
(a pune întrebări de două ori la rând este enervant) și ar trebui cu siguranță să fie idempotent. Din
fericire, debconf evită implicit repetarea întrebărilor, astfel încât acest lucru este în general ușor de
realizat.
Rețineți că scriptul „config” este rulat înainte ca pachetul să fie despachetat. Acesta ar trebui să
utilizeze numai comenzile care se află în pachetele esențiale. Singura dependență a pachetului dvs. care
este garantată a fi îndeplinită atunci când scriptul config este rulat este o dependență (posibil cu o
versiune specificată) de debconf însuși.
Scriptul „config” nu ar trebui să fie nevoit să modifice deloc sistemul de fișiere. Acesta examinează
doar starea sistemului și pune întrebări, iar debconf stochează răspunsurile pentru a fi utilizate
ulterior de scriptul „postinst”. În schimb, scriptul „postinst” nu ar trebui să utilizeze aproape
niciodată debconf pentru a pune întrebări, ci ar trebui să acționeze pe baza răspunsurilor la întrebările
puse de scriptul „config”.
FIȘIERUL DE ȘABLOANE „TEMPLATES”
Un pachet care utilizează debconf dorește probabil să pună câteva întrebări. Aceste întrebări sunt
stocate, sub formă de șablon, în fișierul templates.
La fel ca scriptul config, fișierul templates este pus în secțiunea control.tar.gz a unui deb. Formatul
său este similar cu cel al unui fișier de control debian; un set de strofe separate prin linii goale,
fiecare strofă având o formă similară formatului RFC822:
Template: foo/bar
Type: string
Defult: foo
Description: Aceasta este un exemplu de chestionar.
Aceasta este descrierea sa extinsă.
.
Rețineți că:n
- Ca în descrierea unui pachet debian, un punct plasat
singur pe linie marchează începutul unui nou paragraf.
- Majoritatea textului este încadrat în cuvinte, dar textul
cu dublă aliniere este lăsat singur, deci îl puteți folosi
pentru liste de elemente, precum această listă. Fiți atenți,
deoarece acesta nu este încadrat în cuvinte, dacă este
prea lat va arăta urât. Utilizarea lui pentru elemente scurte
este cel mai potrivit (deci acesta este un exemplu prost).
Template: foo/baz
Type: boolean
Description: Destul de clar, nu?
Aceasta este o altă întrebare, de tip boolean.
Pentru câteva exemple reale de fișiere șablon, consultați „/var/lib/dpkg/info/debconf.templates” și alte
fișiere „.templates” din acel director.
Să analizăm pe rând fiecare dintre câmpuri.
Template
Numele șablonului, în câmpul „Template”, este în general precedat de numele pachetului. După
aceea, spațiul de nume este foarte liber; puteți utiliza un aspect plat simplu, precum cel de mai
sus, sau puteți crea „subdirectoare” care să conțină întrebări conexe.
Type Tipul șablonului determină ce tip de element de meniu este afișat utilizatorului. Tipurile
acceptate în prezent sunt:
string Rezultă un câmp de intrare cu formă liberă în care utilizatorul poate introduce orice șir
de caractere.
password
Solicită utilizatorului o parolă. Utilizați această opțiune cu precauție; fiți conștienți
de faptul că parola introdusă de utilizator va fi scrisă în baza de date a debconf.
Probabil ar trebui să eliminați această valoare din baza de date cât mai curând posibil.
boolean
O alegere adevărat/fals (true/false).
select O alegere între una dintre mai multe valori. Opțiunile trebuie specificate într-un câmp
numit „Choices”. Separați valorile posibile cu virgule și spații, astfel:
Choices: da, nu, poate
multiselect
La fel ca tipul de date de selectare, cu excepția faptului că utilizatorul poate alege
orice număr de elemente din lista de opțiuni (sau poate să nu aleagă niciuna dintre ele).
note Mai degrabă decât o întrebare în sine, acest tip de date indică o notă care poate fi
afișată utilizatorului. Ar trebui utilizat numai pentru note importante pe care
utilizatorul ar trebui să le vadă, deoarece debconf se va strădui foarte mult să se asigure
că utilizatorul le vede, oprind instalarea pentru ca acesta să apese o tastă. Cel mai bine
este să le folosiți doar pentru avertizări cu privire la probleme foarte grave, iar tipul
de date error este adesea mai potrivit.
error Acest tip de date este utilizat pentru mesajele de eroare, cum ar fi erorile de validare a
intrărilor. Debconf va afișa o întrebare de acest tip chiar dacă prioritatea este prea mare
sau dacă utilizatorul a văzut-o deja.
title Acest tip de date este utilizat pentru titluri, pentru a fi definite cu comanda SETTITLE.
text Acest tip de date poate fi utilizat pentru fragmente de text, cum ar fi etichetele, care
pot fi utilizate din motive cosmetice în afișajele unor interfețe. Alte interfețe nu îl vor
utiliza deloc. Deocamdată nu are rost să utilizați acest tip de date, deoarece nicio
interfață nu îl acceptă bine. Acesta ar putea fi chiar eliminat în viitor.
Default
Câmpul „Default” indică debconf care ar trebui să fie valoarea implicită. Pentru multiselect,
aceasta poate fi o listă de opțiuni, separate prin virgule și spații, similar câmpului „Choices”.
Pentru select, ar trebui să fie una dintre opțiuni. Pentru boolean, este „true” sau „false”, în
timp ce poate fi orice pentru un string și este ignorat pentru password.
Nu faceți greșeala de a crede că câmpul Default conține „valoarea” întrebării sau că poate fi
utilizat pentru a modifica valoarea întrebării. Nu este așa și nici nu poate fi, ci doar oferă o
valoare implicită pentru prima dată când este afișată întrebarea. Pentru a furniza o valoare
implicită care se modifică din mers, ar trebui să utilizați comanda SET pentru a modifica valoarea
unei întrebări.
Description
Câmpul „ Description ”, ca și descrierea unui pachet Debian, are două părți: O descriere scurtă și
o descriere extinsă. Rețineți că unele interfețe debconf nu afișează descrierea lungă sau o pot
afișa doar dacă utilizatorul cere ajutor. Așadar, descrierea scurtă ar trebui să fie capabilă „să
se descurce” singură.
Dacă nu vă puteți gândi la o descriere lungă, atunci mai întâi, gândiți-vă mai mult. Adresați-vă
la debian-devel. Cereți ajutor. Luați un curs de scriere! Acea descriere extinsă este importantă.
Dacă după toate astea tot nu vă vine nimic în minte, lăsați-o goală. Nu are rost să duplicați
descrierea scurtă.
Textul din descrierea extinsă va fi încadrat în cuvinte, cu excepția cazului în care este prefixat
de un spațiu alb suplimentar (în afară de spațiul necesar). Îl puteți împărți în paragrafe
separate punând „ .” pe o linie de sine stătătoare între ele.
ÎNTREBĂRI
O întrebare este o instanță a unui șablon. Solicitând debconf să afișeze o întrebare, scriptul dvs.
„config” poate interacționa cu utilizatorul. Atunci când debconf încarcă un fișier de șabloane (acest
lucru se întâmplă ori de câte ori se execută un script „config” sau „postinst”), acesta creează automat o
instanță de întrebare din fiecare șablon. De fapt, este posibilă crearea de instanțe de mai multe
întrebări independente din același șablon (utilizând comanda REGISTER), dar acest lucru este rareori
necesar. Șabloanele sunt date statice care provin din fișierul de șabloane, în timp ce întrebările sunt
utilizate pentru a stoca date dinamice, cum ar fi valoarea curentă a întrebării, dacă un utilizator a
văzut o întrebare și așa mai departe. Țineți cont de distincția dintre un șablon și o întrebare, dar nu
vă faceți prea multe griji cu privire la aceasta.
ȘABLOANE PARTAJATE
De fapt, este posibil să existe un șablon și o întrebare care sunt partajate între un set de pachete.
Toate pachetele trebuie să furnizeze o copie identică a șablonului în fișierele lor de șabloane. Acest
lucru poate fi util dacă o serie de pachete trebuie să pună aceeași întrebare și doriți să deranjați
utilizatorul o singură dată cu aceasta. Șabloanele partajate sunt în general plasate în pseudo-directorul
shared/ din spațiul de nume al șabloanelor debconf.
PROTOCOLUL DEBCONF
Scripturile „config” comunică cu debconf utilizând protocolul debconf. Acesta este un protocol simplu
orientat pe linii, similar protocoalelor comune de Internet, cum ar fi SMTP. Scriptul „config” trimite o
comandă către debconf prin scrierea comenzii la ieșirea standard. Apoi poate citi răspunsul debconf de la
intrarea standard.
Răspunsul Debconf poate fi împărțit în două părți: Un cod de rezultat numeric (primul cuvânt al
răspunsului) și un cod de rezultat extins opțional (restul răspunsului). Codul numeric utilizează 0
pentru a indica succesul, iar alte numere pentru a indica diferite tipuri de eșecuri. Pentru detalii
complete, consultați tabelul din documentul de specificații debconf al politicii Debian.
Codul de returnare extins este, în general, liber și nespecificat, astfel încât, în general, ar trebui să
îl ignorați și cu siguranță nu ar trebui să încercați să îl analizați într-un program pentru a afla ce
face debconf. Excepție fac comenzile precum GET, care fac ca o valoare să fie returnată în codul de
răspuns extins.
În general, veți dori să utilizați o bibliotecă specifică limbajului care să se ocupe de configurarea
acestor conexiuni la debconf și de comunicarea cu acesta.
Pentru moment, aici sunt comenzile din protocol. Aceasta nu este definiția definitivă, consultați
documentul de specificații debconf al politicii Debian pentru aceasta.
VERSION număr
În general, nu este necesar să utilizați această comandă. Aceasta schimbă cu debconf numărul
versiunii protocolului care este utilizat. Versiunea actuală a protocolului este 2.0, iar
versiunile din seria 2.x vor fi retrocompatibile. Puteți specifica numărul versiunii protocolului
pe care îl vorbiți, iar debconf va returna versiunea protocolului pe care îl vorbește în codul de
rezultat extins. Dacă versiunea pe care o specificați este prea mică, debconf va răspunde cu codul
numeric 30.
CAPB capacități
În general, nu este necesar să utilizați această comandă. Aceasta schimbă cu debconf o listă de
capacități acceptate (separate prin spații). Capacitățile pe care atât dumneavoastră, cât și
debconf le acceptați vor fi utilizate, iar debconf va răspunde cu toate capacitățile pe care le
acceptă.
Dacă „escape” se găsește printre capacitățile dvs., debconf se va aștepta ca comenzile pe care i
le trimiteți să aibă bare oblice și linii noi eludate (ca \\ și respectiv \n) și va eluda la
rândul său bare oblice și linii noi în răspunsurile sale. Acest lucru poate fi utilizat, de
exemplu, pentru a înlocui șiruri de caractere cu mai multe linii în șabloane sau pentru a obține
descrieri extinse cu mai multe linii în mod fiabil utilizând METAGET. În acest mod, trebuie să
eludați singuri textul de intrare (dacă doriți, puteți utiliza debconf-escape(1) pentru a vă ajuta
în acest sens), iar bibliotecile confmodule vor elimina eludarea din răspunsuri pentru
dumneavoastră.
SETTITLE întrebare
Aceasta definește titlul pe care debconf îl afișează utilizatorului, utilizând descrierea scurtă a
șablonului pentru întrebarea specificată. Șablonul trebuie să fie de tip title. Rareori trebuie să
utilizați această comandă, deoarece debconf poate genera automat un titlu bazat pe numele
pachetului dvs.
Definirea titlurilor dintr-un șablon înseamnă că acestea sunt stocate în același loc ca și restul
întrebărilor debconf și permite traducerea lor.
TITLE șir
Aceasta stabilește titlul pe care debconf îl afișează utilizatorului la șirul specificat.
Utilizarea comenzii SETTITLE este în mod normal de preferat, deoarece permite traducerea titlului.
INPUT prioritate întrebare
Solicită debconf să se pregătească pentru a afișa o întrebare utilizatorului. Întrebarea nu este
afișată efectiv până când nu este emisă o comandă GO; acest lucru permite ca mai multe comenzi
INPUT să fie date în serie, pentru a construi un set de întrebări, care ar putea fi adresate toate
pe un singur ecran.
Câmpul de prioritate îi indică lui debconf cât de important este ca această întrebare să fie
afișată utilizatorului. Valorile priorității sunt:
low Elemente foarte banale care au valori implicite care vor funcționa în marea majoritate a
cazurilor; doar obsedații de control le văd.
medium Elemente normale care au valori implicite rezonabile.
high Elemente care nu au o valoare implicită rezonabilă.
critical
Elemente care probabil vor distruge sistemul fără intervenția utilizatorului.
Debconf decide dacă întrebarea este afișată efectiv, pe baza priorității sale, dacă utilizatorul a
mai văzut-o înainte și ce interfață este utilizată. Dacă întrebarea nu va fi afișată, debconf
răspunde cu codul 30.
GO
Îi indică lui debconf să afișeze utilizatorului setul acumulat de întrebări (din comenzile INPUT).
Dacă capacitatea de copiere de rezervă este acceptată și utilizatorul indică faptul că dorește să
copieze de rezervă un pas, debconf răspunde cu codul 30.
CLEAR Șterge setul acumulat de întrebări (de la comenzile INPUT) fără a le afișa.
BEGINBLOCK
ENDBLOCK
Unele interfețe debconf pot afișa utilizatorului un număr de întrebări simultan. Poate că în
viitor o interfață va putea chiar să grupeze aceste întrebări în blocuri pe ecran. BEGINBLOCK și
ENDBLOCK pot fi plasate în jurul unui set de comenzi INPUT pentru a indica blocuri de întrebări
(iar blocurile pot fi chiar imbricate). Deoarece nicio interfață debconf nu este încă atât de
sofisticată, aceste comenzi sunt ignorate pentru moment.
STOP Această comandă îi indică lui debconf că ați terminat de dialogat cu el. Adesea, debconf poate
detecta terminarea programului dvs. și această comandă nu este necesară.
GET întrebare
După ce utilizați INPUT și GO pentru a afișa o întrebare, puteți utiliza această comandă pentru a
obține valoarea introdusă de utilizator. Valoarea este returnată în codul de rezultat extins.
SET întrebare valoare
Aceasta stabilește valoarea unei întrebări și poate fi utilizată pentru a înlocui valoarea
implicită cu ceva ce programul dvs. calculează din mers.
RESET întrebare
Aceasta readuce întrebarea la valoarea sa implicită (așa cum este specificată în câmpul „ Default
” al șablonului său).
SUBST întrebare cheie valoare
Întrebările pot avea substituții încorporate în câmpurile „Description” și „Choices” (utilizarea
substituțiilor în câmpurile „Choices” este un pic de improvizație; un mecanism mai bun va fi
dezvoltat în cele din urmă). Aceste substituții arată ca „${key}”. Atunci când întrebarea este
afișată, substituțiile sunt înlocuite cu valorile lor. Această comandă poate fi utilizată pentru a
defini valoarea unei substituții. Acest lucru este util dacă trebuie să afișați utilizatorului un
mesaj pe care nu îl puteți codifica în interiorul codului din fișierul de șabloane.
Nu încercați să utilizați SUBST pentru a schimba valoarea implicită a unei întrebări; nu va
funcționa, deoarece există o comandă SET explicită pentru acest scop.
FGET întrebare fanion
Întrebările pot avea asociate fanioane. Fanioanele pot avea o valoare de „true” sau „false”.
Această comandă returnează valoarea unui fanion.
FSET întrebare fanion valoare
Aceasta stabilește valoarea fanionului unei întrebări. Valoarea trebuie să fie „true” sau „false”.
Un fanion comun este fanionul „seen”. În mod normal, acesta este activat numai dacă un utilizator
a văzut deja o întrebare. De obicei, Debconf afișează întrebările utilizatorilor numai dacă
aceștia au fanionul seen definit la „false” (sau dacă reconfigurează un pachet). Uneori doriți ca
utilizatorul să vadă din nou o întrebare - în aceste cazuri, puteți defini fanionul seen la
„false” pentru a forța debconf să o afișeze din nou.
METAGET întrebare câmp
Aceasta returnează valoarea oricărui câmp din șablonul asociat unei întrebări ( descrierea
Description, de exemplu).
REGISTER șablon întrebare
Aceasta creează o întrebare nouă care este legată de un șablon. În mod implicit, fiecare șablon
are asociată o întrebare cu același nume. Cu toate acestea, orice număr de întrebări poate fi
asociat cu un șablon, iar acest lucru vă permite să creați mai multe astfel de întrebări.
UNREGISTER întrebare
Aceasta elimină o întrebare din baza de date.
PURGE Apelați această comandă în scriptul dvs. „postrm” atunci când pachetul dvs. este purjat. Aceasta
elimină toate întrebările pachetului dvs. din baza de date a debconf.
X_LOADTEMPLATEFILE /ruta/la/templates [proprietar]
Această extensie încarcă fișierul șablon specificat în baza de date a debconf. Proprietarul este
implicit pachetul care este configurat cu debconf.
Iată un exemplu simplu de protocol debconf în acțiune.
INPUT medium debconf/frontend
30 question skipped
FSET debconf/frontend seen false
0 false
INPUT high debconf/frontend
0 question will be asked
GO
[ Aici debconf afișează o întrebare pentru utilizator. ]
0 ok
GET no/such/question
10 no/such/question doesn't exist
GET debconf/frontend
0 Dialog
BIBLIOTECI
Configurarea lucrurilor astfel încât să puteți comunica cu debconf și să dialogați cu el prin intermediul
protocolului debconf este un pic prea mult de lucru, așa că există câteva biblioteci mici pentru a ușura
această corvoadă minoră.
Pentru programarea în shell, există biblioteca „/usr/share/debconf/confmodule”, pe care o puteți utiliza
ca sursă în partea de sus a unui script de tip shell și care vă permite să comunicați cu debconf într-un
mod destul de natural, utilizând versiuni cu minuscule ale comenzilor protocolului debconf, care sunt
prefixate cu „db_” (de exemplu, „db_input” și „db_go”). Pentru detalii, consultați confmodule(3) .
Programatorii Perl pot utiliza modulul perl Debconf::Client::ConfModule(3pm), iar programatorii python
pot utiliza modulul python debconf.
Restul acestui manual va utiliza biblioteca „/usr/share/debconf/confmodule” în exemple de scripturi
shell. Iată un exemplu de script de configurare care utilizează această bibliotecă, care pune doar o
întrebare:
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
db_set mypackage/reboot-now false
db_input high mypackage/reboot-now || true
db_go || true
Observați utilizarea lui „|| true” pentru a preveni moartea scriptului dacă debconf decide că nu poate
afișa o întrebare sau dacă utilizatorul încearcă să dea înapoi. În aceste situații, debconf returnează un
cod de ieșire diferit de zero și, din moment ce acest script shell este definit cu „ -e”, un cod de
ieșire nepreluat l-ar face să abandoneze.
Și aici este un script „postinst” corespunzător, care utilizează răspunsul utilizatorului la întrebare
pentru a vedea dacă sistemul ar trebui repornit (un exemplu destul de absurd..):
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
db_get mypackage/reboot-now
if [ "$RET" = true ]; then
shutdown -r now
fi
Observați utilizarea variabilei $RET pentru a obține codul de răspuns extins de la comanda GET, care
conține răspunsul utilizatorului la întrebare.
SCRIPTUL POSTINST
Ultima secțiune conținea un exemplu de script „postinst” care utilizează debconf pentru a obține valoarea
unei întrebări și pentru a acționa în funcție de aceasta. Iată câteva lucruri de care trebuie să țineți
cont atunci când scrieți scripturi „postinst” care utilizează debconf:
* Evitați să puneți întrebări în „postinst”. În schimb, scriptul „config” ar trebui să pună
întrebări utilizând debconf, astfel încât pre-configurarea să funcționeze.
* Întotdeauna sursa „/usr/share/debconf/confmodule” în partea de sus a scriptului dvs. „postinst”,
chiar dacă nu veți executa nicio comandă db_* în acesta. Acest lucru este necesar pentru a vă
asigura că scriptul „config” are șansa de a rula (consultați secțiunea TRUCURI pentru detalii).
* Evitați să trimiteți ceva la ieșirea standard (stdout) în „postinst”, deoarece acest lucru poate
crea confuzie în debconf, iar „postinst” nu ar trebui să fie oricum prea „vorbăreț”. Ieșirea la
ieșirea de eroare standard este ok, dacă este necesar.
* Dacă scriptul dvs. „postinst” lansează un demon, asigurați-vă că îi indicați lui debconf să
efectueze STOP la sfârșit, deoarece debconf poate deveni puțin confuz cu privire la momentul în
care scriptul dvs. postinst este gata.
* Asigurați-vă că scriptul „postinst” acceptă un prim parametru „reconfigure”. Acesta îl poate trata
la fel ca „configure”. Acesta va fi utilizat într-o versiune ulterioară a debconf pentru a anunța
scripturile „postinist” atunci când sunt reconfigurate.
ALTE SCRIPTURI
Pe lângă scripturile „config” și „postinst”, puteți utiliza debconf în oricare dintre celelalte scripturi
ale întreținătorului. Cel mai frecvent, veți utiliza debconf în „postrm”, pentru a apela comanda PURGE
atunci când pachetul dvs. este purjat, pentru a curăța intrările sale din baza de date debconf. (Apropo,
acest lucru este configurat automat pentru dvs. de dh_installdebconf(1),).
O utilizare mai implicată a debconf ar fi dacă doriți să o utilizați în „postrm” atunci când pachetul
dvs. este curățat, pentru a pune o întrebare despre ștergerea a ceva. Sau poate descoperiți că trebuie să
îl folosiți în „preinst” sau „prerm” pentru un motiv oarecare. Toate aceste utilizări vor funcționa, deși
vor implica probabil adresarea de întrebări și luarea de măsuri în funcție de răspunsuri în același
program, mai degrabă decât separarea celor două activități, așa cum se face în scripturile „config” și
„postinst”.
Rețineți că, dacă singura utilizare a debconf de către pachetul dvs. este în „postrm”, ar trebui să
faceți ca scriptul „postinst” a pachetului dvs. să includă „/usr/share/debconf/confmodule”, pentru a da
debconf o șansă de a încărca fișierul șabloanelor dvs. în baza sa de date. Apoi, șabloanele vor fi
disponibile atunci când pachetul dvs. este purjat.
De asemenea, puteți utiliza debconf în alte programe de sine stătătoare. Problema la care trebuie să fiți
atenți aici este că debconf nu este destinat să fie și nu trebuie să fie utilizat ca un registru. La urma
urmei, acesta este unix, iar programele sunt configurate de fișiere din „/etc”, nu de o bază de date
nebuloasă debconf (care oricum este doar o cache și ar putea fi distrusă). Așa că gândiți-vă bine înainte
de a utiliza debconf într-un program autonom.
Există momente în care poate avea sens, cum ar fi în programul apt-setup care utilizează debconf pentru a
solicita utilizatorului o manieră consecventă cu restul procesului de instalare debian și acționează
imediat în funcție de răspunsurile acestuia pentru a configura fișierul sources.list al apt.
LOCALIZAREA
Debconf acceptă traducerea fișierelor șablon. Acest lucru se realizează prin adăugarea mai multor
câmpuri, cu text tradus în ele. Oricare dintre câmpuri poate fi tradus. De exemplu, ați putea dori să
traduceți descrierea în română. Trebuie doar să creați un câmp numit „Description-ro” care să conțină
traducerea. Dacă un câmp tradus nu este disponibil, debconf revine la câmpul normal în limba engleză.
Pe lângă câmpul „Description”, trebuie să traduceți câmpul „Choices” al unui șablon select sau
multiselect. Asigurați-vă că listați opțiunile traduse în aceeași ordine în care apar în câmpul principal
„Choices”. Nu este necesar să traduceți câmpul „Default” al unei întrebări select sau multiselect, iar
valoarea întrebării va fi returnată automat în limba engleză.
Vă va fi mai ușor să gestionați traducerile dacă le păstrați în fișiere separate; un fișier pentru
fiecare traducere. În trecut, programele debconf-getlang(1) și debconf-mergetemplate(1) erau utilizate
pentru a gestiona fișierele debian/template.ll. Acestea au fost înlocuite de pachetul po-debconf(7), care
vă permite să gestionați traducerile debconf în fișiere .po, la fel ca orice alte traduceri. Traducătorii
dvs. vă vor mulțumi pentru utilizarea acestui nou mecanism îmbunătățit.
Pentru detalii despre po-debconf, consultați pagina sa de manual. Dacă utilizați debhelper, convertirea
la po-debconf este la fel de simplă ca și rularea comenzii debconf-gettextize(1) o dată și adăugarea unui
Build-Dependency în po-debconf și în debhelper (>= 4.1.13).
PUNÂND TOTUL CAP LA CAP
Deci, aveți un script „config”, un fișier templates, un script „postinst” care utilizează debconf și așa
mai departe. Punerea acestor piese împreună într-un pachet debian nu este dificilă. O puteți face manual
sau puteți utiliza dh_installdebconf(1), care va fuziona șabloanele traduse, va copia fișierele în
locurile potrivite pentru dvs. și poate chiar genera apelul la PURGE care ar trebui să apară în scriptul
„postrm”. Asigurați-vă că pachetul dvs. depinde de debconf (>= 0.5), deoarece versiunile anterioare nu
erau compatibile cu tot ceea ce este descris în acest manual. Și ați terminat.
Este în regulă, cu excepția testării, a depanării și a utilizării debconf pentru lucruri mai interesante
decât adresarea unor întrebări de bază. Pentru asta, citiți mai departe..
DEPANAREA
Deci, aveți un pachet care ar trebui să utilizeze debconf, dar nu prea funcționează. Poate că debconf pur
și simplu nu pune întrebarea pe care ați stabilit-o. Sau poate se întâmplă ceva mai ciudat; se învârte la
nesfârșit într-un fel de buclă, sau mai rău. Din fericire, debconf are o mulțime de facilități de
depanare.
DEBCONF_DEBUG
Primul lucru pe care trebuie să îl căutați este variabila de mediu DEBCONF_DEBUG. Dacă definiți și
exportați DEBCONF_DEBUG=developer, debconf va afișa la ieșirea de eroare standard o captură a
protocolului debconf în timp ce programul dvs. rulează. Acesta va arăta cam așa - greșeala de
tastare este evidențiată:
debconf (developer): <-- input high debconf/frontand
debconf (developer): --> 10 "debconf/frontand" doesn't exist
debconf (developer): <-- go
debconf (developer): --> 0 ok
Este destul de util să utilizați interfața „readline” a debconf atunci când depanați (în opinia
autorului), deoarece întrebările nu vă încurcă, iar toate rezultatele de depanare sunt ușor de
păstrat și de înregistrat.
DEBCONF_C_VALUES
Dacă această variabilă de mediu este definită la „true”, interfața va afișa valorile din câmpurile
Choices-C (dacă sunt prezente) ale șabloanelor select și multiselect mai degrabă decât valorile
descriptive.
debconf-communicate
Un alt instrument util este programul debconf-communicate(1). Porniți-l și puteți comunica cu
protocolul debconf în mod interactiv cu debconf. Aceasta este o modalitate excelentă de a încerca
lucruri din mers.
debconf-show
Dacă un utilizator raportează o problemă, debconf-show(1) poate fi utilizat pentru a afișa toate
întrebările deținute de pachetul dvs., afișând valorile acestora și dacă utilizatorul le-a văzut.
.debconfrc
Pentru a evita ciclul adesea plictisitor de compilare/ instalare/depanare, poate fi util să vă
încărcați șabloanele cu debconf-loadtemplate(1) și să vă rulați manual scriptul „config” cu
comanda debconf(1). Cu toate acestea, trebuie să faceți toate acestea ca root, nu? Nu este prea
grozav. Și ideal ar fi să puteți vedea cum arată o instalare proaspătă a pachetului dumneavoastră,
cu o bază de date debconf curată.
Se pare că, dacă configurați un fișier „~/.debconfrc” pentru un utilizator normal, care indică un
fișier config.dat și template.dat personal pentru utilizator, puteți încărca șabloane și rula
scripturi „config” cât doriți, fără acces root. Dacă doriți să începeți din nou cu o bază de date
curată, pur și simplu îndepărtați fișierele *.dat.
Pentru detalii despre această configurare, consultați debconf.conf(5), și rețineți că
„/etc/debconf.conf” este un model bun pentru un fișier „~/.debconfrc” personal.
PROGRAMARE AVANSATĂ CU DEBCONF
Gestionarea fișierelor de configurare
Mulți dintre dvs. par să dorească să utilizeze debconf pentru a ajuta la gestionarea fișierelor de
configurare care fac parte din pachetul dvs. Poate că nu există o valoare implicită bună pentru a fi
livrată într-un pachet și, prin urmare, doriți să utilizați debconf pentru a întreba utilizatorul și a
scrie un fișier de configurare pe baza răspunsurilor sale. Acest lucru pare destul de ușor de făcut, dar
apoi vă gândiți la actualizări și ce să faceți atunci când cineva modifică fișierul de configurare pe
care îl generați, și dpkg-reconfigure, și ...
Există o mulțime de modalități de a face acest lucru, iar cele mai multe dintre ele sunt greșite și vă
vor aduce deseori rapoarte de eroare enervante. Iată o modalitate corectă de a face acest lucru. Aceasta
presupune că fișierul dvs. de configurare este de fapt doar o serie de variabile shell care trebuiesc
definite, cu comentarii între ele, și astfel tot ce aveți de făcut, este doar să includeți sursa
fișierului (ce conține valorile acestor variabile) pentru a-l „încărca”. Dacă aveți un format mai
complicat, citirea (și scrierea) acestuia devine un pic mai complicată.
Scriptul dvs. de configurare va arăta cam așa:
#!/bin/sh
CONFIGFILE=/etc/foo.conf
set -e
. /usr/share/debconf/confmodule
# Încarcă fișierul de configurare, dacă există.
if [ -e $CONFIGFILE ]; then
. $CONFIGFILE || true
# Stochează valorile din fișierul de configurare
# în debconf db.
db_set mypackage/foo "$FOO"
db_set mypackage/bar "$BAR"
fi
# Pune întrebări.
db_input medium mypackage/foo || true
db_input medium mypackage/bar || true
db_go || true
Iar scriptul „postinst” va arăta cam așa:
#!/bin/sh
CONFIGFILE=/etc/foo.conf
set -e
. /usr/share/debconf/confmodule
# Generează fișierul de configurare, dacă acesta nu există.
# O alternativă este să copiați un fișier șablon din altă parte.
if [ ! -e $CONFIGFILE ]; then
echo "# Fișierul de configurare pentru pachetul meu" > $CONFIGFILE
echo "FOO=" >> $CONFIGFILE
echo "BAR=" >> $CONFIGFILE
fi
# Înlocuiește valorile din db debconf.
# Sunt posibile optimizări evidente aici.
# «cp» înainte de «sed» ne asigură că nu încurcăm
# proprietarul și permisiunile fișierului de configurare.
# the config file's ownership and permissions.
db_get mypackage/foo
FOO="$RET"
db_get mypackage/bar
BAR="$RET"
cp -a -f $CONFIGFILE $CONFIGFILE.tmp
# Dacă administratorul a șters sau a comentat unele variabile,
# dar apoi le-a definit prin debconf, (re)adăugați-le în conffile.
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
Luați în considerare modul în care aceste două scripturi tratează toate cazurile. La noile instalări,
întrebările sunt adresate de scriptul „config”, iar un nou fișier se configurare este generat de
„postinst”. La actualizări și reconfigurări, fișierul de configurare este citit, iar valorile din acesta
sunt utilizate pentru a modifica valorile din baza de date debconf, astfel încât modificările manuale ale
administratorului să nu fie pierdute. Întrebările sunt puse din nou (și pot fi afișate sau nu). Apoi
„postinst” înlocuiește valorile înapoi în fișierul de configurare, lăsând restul acestuia neschimbat.
Permițând utilizatorului să revină la întrebarea anterioară
Puține lucruri sunt mai frustrante atunci când folosești un sistem precum debconf decât să ți se pună o
întrebare, să răspunzi la ea, apoi să treci la un alt ecran cu o nouă întrebare pe el și să-ți dai seama
că ai făcut o greșeală cu ultima întrebare și vrei să te întorci la ea și să descoperi că nu poți.
Deoarece debconf este condus de scriptul dvs. de configurare, acesta nu poate reveni singur la o
întrebare anterioară, dar cu puțin ajutor din partea dvs., poate realiza această „performanță”. Primul
pas este să faceți ca scriptul dvs. de configurare să informeze debconf că este capabil să gestioneze
apăsarea unui buton înapoi de către utilizator. Utilizați comanda CAPB pentru a face acest lucru, trecând
„backup” ca parametru.
Apoi, după fiecare comandă GO, trebuie să verificați dacă utilizatorul a cerut să revină la întrebarea
anterioară (debconf returnează un cod de 30) și, în caz afirmativ, să săriți înapoi la întrebarea
anterioară.
Există mai multe moduri de a scrie structurile de control ale programului dvs. astfel încât acesta să
poată reveni la întrebările anterioare atunci când este necesar. Puteți scrie cod „spaghetti” încărcat de
goto-uri. Sau puteți crea mai multe funcții și folosi recursivitatea. Dar poate cea mai curată și mai
ușoară modalitate este să construiți o mașină de stare. Iată un schelet de mașină de stare pe care îl
puteți completa și extinde.
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
db_capb backup
STATE=1
while true; do
case "$STATE" in
1)
# Două întrebări care nu au legătură.
db_input medium my/question || true
db_input medium my/other_question || true
;;
2)
# Puneți această întrebare numai dacă
# răspunsul la prima întrebare a fost
# afirmativ.
db_get my/question
if [ "$RET" = "true" ]; then
db_input medium my/dep_question || true
fi
;;
*)
# Cazul implicit este detectat atunci când $STATE este mai mare
# decât ultima stare implementată și iese din buclă. Acest lucru
# necesită ca stările să fie numerotate consecutiv de la 1 fără
# întreruperi, deoarece cazul implicit va fi introdus și dacă există
# o întrerupere în numerotare
break # iese din bucla „while”.
;;
esac
if db_go; then
STATE=$((STATE + 1))
else
STATE=$((STATE - 1))
fi
done
if [ $STATE -eq 0 ]; then
# Utilizatorul a cerut să revină de la prima întrebare.
# Acest caz este problematic. Instalarea obișnuită a
# pachetelor dpkg și apt nu este capabilă să facă o
# copie de rezervă a întrebărilor între pachete, așa
# cum este scris acest lucru, astfel încât va ieși
# lăsând pachetul neconfigurat - probabil cel mai
# bun mod de a gestiona situația.
exit 10
fi
Rețineți că, dacă scriptul dvs. de configurare nu face decât să pună câteva întrebări fără legătură între
ele, atunci nu este nevoie de mașina de stare. Doar puneți-le pe toate și „GO”; debconf va face tot
posibilul să le prezinte pe toate într-un singur ecran, iar utilizatorul nu va trebui să se întoarcă.
Prevenirea buclelor infinite
O problemă cu debconf apare dacă aveți o buclă în scriptul de configurare. Să presupunem că solicitați o
intrare și o validați, iar dacă aceasta nu este validă, faceți o buclă:
ok=”
do while [ ! "$ok" ];
db_input low foo/bar || true
db_go || true
db_get foo/bar
if [ "$RET" ]; then
ok=1
fi
done
Acest lucru pare în regulă la prima vedere. Dar gândiți-vă ce se întâmplă dacă valoarea lui foo/bar este
„” atunci când se intră în această buclă, iar utilizatorul are stabilită o prioritate ridicată sau
utilizează o interfață neinteractivă și, prin urmare, nu i se solicită cu adevărat un răspuns. Valoarea
lui foo/bar nu este modificată de db_input și, prin urmare, nu trece testul și intră în buclă. Și bucle
...
O soluție este să vă asigurați că, înainte de a intra în buclă, valoarea foo/bar este stabilită la ceva
care va trece testul în buclă. Astfel, de exemplu, dacă valoarea implicită a foo/bar este „1”, atunci
puteți pune RESET foo/bar chiar înainte de a intra în buclă.
O altă soluție este să verificați codul de răspuns al comenzii INPUT. Dacă este 30, atunci utilizatorului
nu i se arată întrebarea pe care i-ați pus-o și ar trebui să ieșiți din buclă.
Alegerea dintre pachetele conexe
Uneori poate fi instalat un set de pachete conexe și doriți să întrebați utilizatorul care dintre acestea
ar trebui să fie utilizate în mod implicit. Exemple de astfel de seturi sunt administratorii de ferestre
sau fișierele de dicționar ispell.
Deși ar fi posibil ca fiecare pachet din set să solicite pur și simplu „Acest pachet ar trebui să fie
implicit?”, acest lucru duce la o mulțime de întrebări repetitive dacă sunt instalate mai multe pachete.
Este posibil ca debconf să prezinte o listă a tuturor pachetelor din set și să permită utilizatorului să
aleagă între ele. Iată cum.
Faceți ca toate pachetele din set să utilizeze un șablon comun. Ceva de genul acesta:
Template: shared/window-manager
Type: select
Choices: ${choices}
Description: Selectați administratorul implicit de ferestre.
Selectați administratorul de ferestre care va fi pornit
implicit la pornirea X.
Fiecare pachet ar trebui să includă o copie a șablonului. Apoi ar trebui să includă un cod ca acesta în
scriptul său „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
Este necesară o mică explicație. În momentul în care scriptul dvs. de configurare rulează, debconf a
citit deja toate șabloanele pentru pachetele care sunt instalate. Deoarece setul de pachete are o
întrebare comună, debconf înregistrează acest fapt în câmpul „owners”. Printr-o coincidență ciudată,
formatul câmpului owners este același cu cel al câmpului „choices” (o listă de valori delimitată prin
virgule și spații).
Comanda METAGET poate fi utilizată pentru a obține lista de proprietari și lista de opțiuni. Dacă acestea
sunt diferite, atunci a fost instalat un pachet nou. Prin urmare, utilizați comanda SUBST pentru a
modifica lista de opțiuni pentru a fi aceeași cu lista de proprietari și puneți întrebarea.
Atunci când un pachet este eliminat, probabil doriți să vedeți dacă acel pachet este alegerea selectată
în prezent și, în caz afirmativ, să solicitați utilizatorului să selecteze un alt pachet pentru a-l
înlocui.
Acest lucru poate fi realizat prin adăugarea unui text ca acesta în scripturile „prerm” ale tuturor
pachetelor aferente (înlocuind <package> cu numele pachetului):
if [ -e /usr/share/debconf/confmodule ]; then
. /usr/share/debconf/confmodule
# Nu mai solicit această întrebare.
db_unregister shared/window-manager
# Vedeți dacă întrebarea comună mai există.
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 [ "<package>" = "$RET" ] ; then
db_fset shared/window-manager seen false
db_input high shared/window-manager || true
db_go || true
fi
# Acum faceți orice a făcut scriptul „postinst” pentru a actualiza
# legătura simbolică a administratorului de ferestre.
fi
fi
TRUCURI
Debconf nu este în prezent complet integrat în dpkg (dar vreau să schimb acest lucru în viitor) și, prin
urmare, sunt necesare unele trucuri murdare.
Cea mai gravă dintre acestea implică rularea scriptului „config”. Modul în care funcționează acum este că
scriptul „config” va fi rulat atunci când pachetul este preconfigurat. Apoi, când se execută scriptul
„postinst”, se pornește din nou debconf. Debconf observă că este utilizat de scriptul „postinst”, așa că
pornește și rulează scriptul „config”. Totuși, acest lucru poate funcționa numai dacă scriptul dvs.
„postinst” încarcă una dintre bibliotecile debconf, astfel încât scripturile „postinst” trebuie să aibă
întotdeauna grijă să facă acest lucru. Sperăm să rezolvăm această problemă mai târziu prin adăugarea unui
suport explicit pentru debconf în dpkg. Programul debconf(1) este un pas în această direcție.
O problemă conexă este să faceți debconf să ruleze atunci când un script „config”, „postinst” sau alt
program care îl utilizează pornește. La urma urmei, acestea se așteaptă să poată comunica imediat cu
debconf. Modul în care se realizează acest lucru pentru moment este că, atunci când un astfel de script
încarcă o bibliotecă debconf (cum ar fi „/usr/share/debconf/confmodule”), iar debconf nu rulează deja,
acesta este pornit și o nouă copie a scriptului este re-executată. Singurul rezultat notabil este că
trebuie să puneți linia care încarcă o bibliotecă debconf chiar în partea de sus a scriptului, altfel se
vor întâmpla lucruri ciudate. Sperăm să rezolvăm această problemă mai târziu, schimbând modul în care
debconf este invocat și transformându-l în ceva mai asemănător unui demon tranzitoriu.
Este destul de complicat modul în care debconf își dă seama ce fișiere de șabloane să încarce și când să
le încarce. Atunci când scripturile „config”, „preinst” și „postinst” apelează debconf, acesta își va da
seama automat unde se află fișierul de șabloane și îl va încărca. Programele autonome care utilizează
debconf vor face ca debconf să caute fișiere de tip șablon în
„/usr/share/debconf/templates/progname.templates”. Iar dacă un script „postrm” dorește să utilizeze
debconf la momentul purjării, șabloanele nu vor fi disponibile decât dacă debconf a avut ocazia să le
încarce în scriptul său „postinst”. Acest lucru este murdar, dar mai degrabă inevitabil. În viitor, unele
dintre aceste programe ar putea fi capabile să utilizeze manual debconf-loadtemplate.
Comportamentul istoric al „/usr/share/debconf/confmodule” de a se juca cu descriptorii de fișiere și de a
configura un fd #3 care comunică cu debconf, poate cauza tot felul de probleme atunci când un script
„postinst” rulează un demon, deoarece demonul ajunge să comunice cu debconf, iar debconf nu își poate da
seama când se termină scriptul. Comanda STOP poate rezolva această problemă. În viitor, ne gândim să
facem ca comunicarea debconf să se realizeze prin intermediul unui soclu sau al unui alt mecanism decât
intrarea/ieșirea standard.
Debconf stabilește DEBCONF_RECONFIGURE=1 înainte de a rula scripturile „postinst”, astfel încât un script
„postinst” care trebuie să evite o operație costisitoare atunci când este reconfigurat se poate uita la
această variabilă. Acesta este un „truc”, deoarece lucrul corect ar fi să treceți $1 = „reconfigure”, dar
este dificil să faceți acest lucru fără a rupe toate scripturile „postinst” care utilizează debconf.
Planul de migrare departe de acest „truc” este de a încuraja oamenii să scrie scripturi „postinst” care
acceptă „reconfigure” și, odată ce toți o fac, să înceapă să treacă acest parametru.
CONSULTAȚI ȘI
debconf(7) este ghidul utilizatorului debconf.
Specificația debconf din politica debian este definiția canonică a protocolului debconf, și anume
„/usr/share/doc/debian-policy/debconf_specification.txt.gz”.
debconf.conf(5) conține multe informații utile, inclusiv unele informații despre baza de date principală.
AUTOR
Joey Hess <joeyh@debian.org>
TRADUERE
Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>, 2024
Dacă găsiți o greșeală în traducere, vă rugăm să o raportați autorului acestei traduceri, pe lista de
discuții <debian-l10n-romanian@lists.debian.org> sau trimițând un raport de eroare contra pachetului
„debconf” către sistemul de urmărire al erorilor din Debian (BTS).
DEBCONF-DEVEL(7)