DEBCONF-DEVEL(7) | Miscellaneous Information Manual | DEBCONF-DEVEL(7) |
debconf - руководство разработчика
Данное руководство помогает при разработке пакетов, использующих debconf.
Предполагается, что вы знакомы с debconf как пользователь, а также знакомы с основами создания пакетов debian.
Это руководство начинается с описания двух новых файлов, которые добавляются в пакеты debian, если они используют debconf. Затем объясняется работа протокола debconf и описываются некоторые библиотеки, которые позволят вашим программам работать с ним. В частности обсуждаются другие сценарии для сопровождения, которые обычно используются с debconf: сценарии postinst и postrm. Далее рассматриваются более сложные темы, например, общие шаблоны debconf, отладка и некоторые основные приёмы и ловушки при программировании с debconf. Завершает руководство описание имеющихся недостатков debconf.
Debconf добавляет дополнительный сценарий сопровождения, сценарий config, который служит для настройки сопровождающих сценариев, имеющихся в пакетах debian (postinst, preinst, postrm и prerm). Сценарий config отвечает за выдачу всех вопросов настройки пакета.
Замечание: часто смущает тот факт, что dpkg ссылается на запущенный сценарий пакета postinst как на «настроечный», хотя пакет, который использует debconf часто полностью настроен своим сценарием config ещё до того как postinst даже будет запущен. Такие дела.
Как и postinst, сценарию config передаётся два параметра при запуске. В первом задаётся действие, которое нужно выполнить, а во втором — версия установленного в данный момент пакета. Как и в postinst, вы можете применить dpkg --compare-versions к $2, чтобы выполнить данную команду только при обновлении с определённой версии пакета и тому подобных операций.
Сценарий config может быть запущен в трёх случаях:
Заметим, что так как типичная установка или обновление с помощью apt попадают под случаи 1 и 2, сценарий config обычно запускается дважды. Он ничего не должен делать во второй раз (отвечать на вопросы второй раз подряд раздражает), и определённо должен быть идемпотентен. К счастью, debconf избегает повторения вопросов по умолчанию, поэтому это легко достигается.
Заметим, что сценарий config запускается перед распаковкой пакета. В нём должны использоваться только команды из пакетов первой необходимости. Единственная зависимость пакета, которая будет удовлетворена до запуска сценария config — это сам debconf (возможно указать версию).
Сценарию config ничего не нужно изменять в файловой системе. Он должен просто проверить состояние системы и задать вопросы, а debconf сохранит ответы, которые требуют действий позже из сценария postinst. И наоборот, сценарий postinst не должен использовать debconf для задания вопросов, а вместо этого должен полагаться на ответы, полученные при работе сценария config.
Пакету, использующему debconf, вероятно требуется задать некоторые вопросы. Эти вопросы хранятся в форме шаблона в файле templates.
Как и сценарий config, файл templates находится в секции control.tar.gz deb файла. Его формат похож на формат debian файла control; секции строк, разделённые символами новой строки, каждая строка задана в RFC822-подобной форме:
Template: foo/bar
Type: string
Default: foo
Description: Это
пример
строки
вопроса.
Это её
дополнительное
описание.
.
Заметим
что:
- как и в
описании
пакета debian
точка
в
отдельной
строке
начинает
новый
параграф.
- для
большого
текста
выполняется
перенос на
новую
строку, но
текст
с двойным
отступом
выводится
как есть,
вы можете
использовать
это для
показа
списков
как
сделано
здесь.
Осторожно,
так как
перенос не
выполняется,
это очень
плохо
сказывается
на слишком
длинных
строках.
Используйте
это для
коротких
элементов
(поэтому
это плохой
пример).
Template: foo/baz
Type: boolean
Description: Вроде
всё просто?
Это другой
вопрос,
логического
типа.
Несколько рабочих примеров для файлов templates можно найти в /var/lib/dpkg/info/debconf.templates и других файлах .templates в этом каталоге.
Давайте рассмотрим каждое из полей по очереди..
Не подумайте, что поле значения по умолчанию содержит «ответ» на вопрос, или что он может быть использован для замены ответа на вопрос. Это не так, и не может быть так, он только предоставляет ответ по умолчанию при первом показе вопроса. Чтобы изменить значение по умолчанию на лету, используйте команду SET.
Если вы не можете придумать длинного описания, то сначала подумайте ещё немного. Напишите в debian-devel. Попросите помочь. Возьмите урок по написанию! Длинное описание очень важно. Если после всего этого ничего не приходит в голову, оставьте поле пустым. Нет смысла дублировать то, что уже написано в коротком описании.
Текст в расширенном описании будет переноситься по словам, если он не начинается с дополнительного пробельного символа (после первого обязательного пробела). Вы можете разбить его на параграфы поместив « .» в пустой строке между параграфами.
Вопрос — это проиллюстрированный шаблон. Прося debconf показать вопрос, таким образом ваш сценарий config может взаимодействовать с пользователем. Когда debconf загружает файл templates (это происходит при запуске сценария config или postinst), он автоматически показывает вопрос каждого шаблона. На самом деле можно показать несколько независимых вопросов из одного шаблона (с помощью команды REGISTER), но это требуется редко. Шаблоны — это статические данные из файла templates, а вопросы используются для хранения динамических данных, таких как имеющийся ответ на вопрос, видел ли пользователь уже этот вопрос и тому подобное. Помните об этом различии между шаблоном и вопросом, но не стоит сильно забивать этим голову.
Фактически, есть возможность иметь один шаблон и вопрос сразу для нескольких пакетов. Все пакеты могут предоставлять идентичную копию шаблона в своих файлах templates. Это может быть полезно, если набору пакетов требуется задать один и тот же вопрос, а вы хотите побеспокоить пользователя только один раз. Общие шаблоны обычно помещаются в псевдокаталог shared/ в пространстве имён шаблонов debconf.
Сценарии config взаимодействуют с debconf по протоколу debconf. Это простой однострочный протокол, похожий на основные протоколы интернета, типа SMTP. Сценарий config посылает debconf команду, записывая эту команду в стандартный вывод. Затем, он может прочитать ответ debconf со стандартного ввода.
Ответы debconf можно разделить на две части: числовой код результата (первое слово в ответе) и необязательный расширенный код результата (оставшаяся часть ответа). В числовом коде значение 0 соответствует успешному выполнению, а другие числа указывают на различного вида неудачи. Подробней смотрите таблицу в политике Debian, раздел спецификации debconf.
Расширенный код результата имеет любой вид и никак не стандартизован, поэтому нужно игнорировать его и не пытаться использовать в своей программе для выяснения что делает debconf. Исключение составляют команды типа GET, которая создаёт значение для возврата в расширенном коде результата.
Обычно вы будете использовать библиотеку, которая работает на низком уровне для установления связи с debconf и взаимодействия с ним.
А теперь обсудим команды протокола. Это не полное описание, за ним обращайтесь к документу о политике Debian, раздел спецификации debconf.
Если среди ваших возможностей будет «escape», то debconf будет ожидать, что в посылаемых вами командах символы обратный слеш и новой строки экранированы (\\ и \n соответственно), а в своих ответах будет также это делать. Это может быть использовано, например, для подстановки многострочных строк в шаблонах, или для получения многострочных расширенных описаний, использующихся в METAGET. В этом режиме вы должны сами экранировать входной текст (для этого вы можете использовать команду debconf-escape(1), если хотите), а библиотеки confmodule будут снимать экранирования в ответах за вас.
Установка заголовка из шаблона означает, что они хранятся в том же месте что и все вопросы debconf, и их можно переводить на другие языки.
Поле приоритета говорит debconf насколько важен вопрос, который будет показан пользователю. Значения приоритета:
Debconf сам решает нужно ли вообще показывать вопрос, основываясь на этом приоритете и том, видел ли уже пользователь этот вопрос и какой интерфейс используется для показа. Если вопрос не будет показан, debconf возвращает код 30.
Если поддерживается возможность backup и пользователь потребовал вернуться на шаг назад, то debconf возвратит код 30.
Распространённым флагом является флаг «seen». Обычно он устанавливается только если пользователь уже видел вопрос. Debconf обычно показывает только те вопросы пользователю, у которых флаг seen установлен в «false» (или если происходит процесс перенастройки пакета). Иногда вам нужно чтобы пользователь увидел вопрос снова — в этом случае вы можете установить флаг seen в значение «false», чтобы заставить debconf показать вопрос ещё раз.
Вот простой пример протокола debconf в действии.
INPUT medium debconf/frontend
30 question skipped
FSET debconf/frontend seen false
0 false
INPUT high debconf/frontend
0 question will be asked
GO
[ Здесь debconf
показывает
вопрос
пользователю.
]
0 ok
GET no/such/question
10 no/such/question doesn't exist
GET debconf/frontend
0 Dialog
Настройка окружения для работы с debconf и общение с debconf по протоколу вручную требует слишком больших затрат, поэтому для этого существуют промежуточные библиотеки, которые освобождают человека от этой монотонной работы.
Для программирования на языке оболочки командной строки существует библиотека /usr/share/debconf/confmodule, которую вы можете указать в начале сценария оболочки, и общаться с debconf в довольно естественной манере, используя команды debconf протокола записанные строчными буквами, которые начинаются с «db_» (то есть, «db_input» и «db_go»). Подробней смотрите в confmodule(3).
Программисты на perl могут использовать модуль Debconf::Client::ConfModule(3pm), а программисты на python могут использовать модуль debconf.
В последующих примерах сценариев оболочки руководства будет использована библиотека /usr/share/debconf/confmodule. Вот пример сценария config, который задаёт вопрос с помощью этой библиотеки:
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
db_set mypackage/reboot-now false
db_input high mypackage/reboot-now || true
db_go || true
Заметим, что использование "|| true" предотвращает сценарий от завершения работы, если debconf решит, что не может показать вопрос, или когда пользователь решит вернуться к предыдущему вопросу. В таких ситуациях debconf возвращает ненулевой код возврата, и так как в сценарии оболочки указана set -e, неотловленный код выхода прервёт его работу.
А вот соответствующий сценарий postinst, который использует пользовательский ответ на вопрос, должна ли система быть перезагружена (слегка абсурдный пример..):
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
db_get mypackage/reboot-now
if [ "$RET" = true ]; then
shutdown -r now
fi
Заметим, что используемая переменная $RET получает расширенный код возврата от команды GET, который содержит ответ пользователя на вопрос.
В последнем разделе был приведён пример сценария postinst, который использует debconf для получения ответа на вопрос и выполняет соответствующие действия. Есть несколько вещей о которых нужно помнить при написании сценариев postinst, использующих debconf:
Кроме сценариев config и postinst, вы можете использовать debconf в любом сценарии сопровождения пакета. Наиболее часто вы будете использовать debconf в сценарии postrm, чтобы вызвать команду PURGE при удалении пакета для удаления всех записей о пакете из базы данных debconf (кстати, это настраивается автоматически с помощью dh_installdebconf(1)).
Также debconf может быть использован в сценарии postrm при вычистке пакета чтобы задать вопрос об удалении чего-либо. Или может быть по какой-то причине вам может потребоваться использовать его в preinst или prerm. Везде он будет работать, хотя это вероятно приведёт к выдаче одинаковых вопросов и реакции на ответы в программе, а не к двум разным действиям, как это происходит со сценариями config и postinst.
Заметим, что если ваш пакет использует debconf только в сценарии postrm, вы должны добавить вызов /usr/share/debconf/confmodule в начало сценария postinst, чтобы дать debconf шанс загрузить файл templates в свою базу данных. Затем templates будет доступен во время вычистке пакета.
Также вы можете использовать debconf просто в работе программ. Но не забывайте, что debconf не предназначен для этого, и не должен использоваться как своеобразный реестр. Это всё-таки unix, и настройки программ хранятся в файлах в каталоге /etc, а не в какой-то мутной базе данных debconf (которая в конечном счёте просто кэш и может сломаться). Так что тридцать раз подумайте перед тем как использовать debconf в простых программах.
Есть ситуации когда это имеет смысл, например в программе apt-setup, которая использует debconf для того чтобы пользователь завершил процесс установки debian в похожем интерфейсе, и сразу же применяет эти ответы для настройки файла sources.list программы apt.
Debconf поддерживает локализацию файлов templates. Это достигается добавлением дополнительных полей с переведённым текстом. Любые поля можно переводить. Например, есть желание перевести описание на испанский. Просто создайте поле с именем «Description-es», в котором есть перевод. Если переведённое поле недоступно, debconf использует обычный английский вариант.
Помимо поля «Description», вы можете перевести поле «Choices» из шаблона select или multiselect. Убедитесь, что переведённые значения в списке расположены в том же порядке что и в основном поле «Choices». Вам не нужно переводить поле «Default» из вопроса select или multiselect, ответ на вопрос будет автоматически возвращён на английский.
Вы обнаружите, что для облегчения управления переводами лучше хранить их в отдельных файлах; один файл на перевод. Раньше для управления файлами debian/template.ll использовались программы debconf-getlang(1) и debconf-mergetemplate(1). Теперь эту функцию выполняет пакет po-debconf(7), который позволяет работать с переводами debconf в .po файлах как с любыми другими переводами. Ваши переводчики будут благодарны вам за использование этого нового усовершенствованного механизма.
Подробней о po-debconf смотрите в его справочной странице. Если вы используете debhelper, переведите его в po-debconf просто запустив один раз команду debconf-gettextize(1) и добавьте зависимость в Build-Dependency от po-debconf и от debhelper (>= 4.1.13).
Итак, у вас есть сценарий config, файл templates, сценарий postinst, использующие debconf и так далее. Поместить все эти части в пакет debian несложно. Вы можете сделать это вручную или с помощью dh_installdebconf(1), которая объединяет переведённые шаблоны, копирует файлы в нужные места, и даже генерирует вызов PURGE, который должен быть в сценарии postrm. Убедитесь, что ваш пакет зависит от debconf (>= 0.5), так как более ранние версии несовместимы с всем описанным в руководстве. Всё.
Да, за исключением тестирования, отладки и реального использования debconf для более интересных вещей чем простое задание вопросов. Об этом читайте далее..
Итак, у вас есть пакет, который предположительно использует debconf, но он не совсем работает. Может быть debconf не только задаёт вопросы при настройке. Или может быть что-то странное случается; он крутится в каком-то вечном цикле или хуже. К счастью, debconf обладает множеством средств отладки.
debconf (developer): <-- input high debconf/frontand
debconf (developer): --> 10 "debconf/frontand" doesn't exist
debconf (developer): <-- go
debconf (developer): --> 0 ok
Для отладки довольно полезно использовать интерфейс debconf readline(по мнению автора), поскольку вопросы не мешают и весь отладочный вывод легко сохранить.
Оказывается, если вы настроите файл ~/.debconfrc для обычного пользователя, указав в нём личный config.dat и template.dat, то сможете загружать файлы templates и запускать сценарий config как хочется, без полномочий суперпользователя. Если нужно ещё раз запуститься с чистой базой данных, просто удалите файлы *.dat.
Подробности настройки смотрите в debconf.conf(5), и заметим, что файл /etc/debconf.conf отлично подойдёт как шаблон для личного файла ~/.debconfrc.
Многие из вас хотели бы использовать debconf для управления файлами настройки пакета. Возможно в файлах настройки недостаточно настроек по умолчанию и поэтому вы бы хотели использовать debconf для опроса пользователя и основываясь на его ответах создавать файл настройки. Кажется, что этого легко достичь, но когда вы задумаетесь об обновлении, или когда кто-то ещё изменит файл настройки, созданный вами и про dpkg-reconfigure и ...
Есть много способов сделать это и большинство из них неправильные, а вы будете получать раздражающие отчёты об ошибках. Есть один правильный путь достижения этого. В нём предполагается, что ваш файл настройки состоит из простого набора устанавливаемых переменных оболочки с комментариями, и поэтому вы можете просто выполнить файл для его «загрузки». Если у вас более сложный формат, чтение (и запись) становятся более сложными.
Ваш сценарий config будет выглядеть так:
#!/bin/sh
CONFIGFILE=/etc/foo.conf
set -e
. /usr/share/debconf/confmodule
# Загрузить
файл
настройки,
если он
существует.
if [ -e $CONFIGFILE ]; then
. $CONFIGFILE || true
# Сохранить
значения
из файла
настройки
в
# базу
данных debconf.
db_set mypackage/foo "$FOO"
db_set mypackage/bar "$BAR"
fi
# Задать
вопросы.
db_input medium mypackage/foo || true
db_input medium mypackage/bar || true
db_go || true
А сценарий postinst будет выглядеть так:
#!/bin/sh
CONFIGFILE=/etc/foo.conf
set -e
. /usr/share/debconf/confmodule
#
Сгенерировать
файл
настройки,
если он не
существует.
# Или
скопировать
из файла
шаблона
# откуда-то
ещё.
if [ ! -e $CONFIGFILE ]; then
echo "# Config file for my package" > $CONFIGFILE
echo "FOO=" >> $CONFIGFILE
echo "BAR=" >> $CONFIGFILE
fi
# Выполнить
подстановку
значений
из базы
данных debconf.
# Здесь явно
возможна
оптимизация.
# Команда cp
перед sed
проверяет,
что мы не
испортили
# права
доступа и
владельца
файла
настройки.
db_get mypackage/foo
FOO="$RET"
db_get mypackage/bar
BAR="$RET"
cp -a -f $CONFIGFILE $CONFIGFILE.tmp
# Если
администратор
удалил или
закомментировал
какие-то
переменные,
но
# после
задал их
через debconf,
добавим(пересоздадим)
их в файле
# настройки.
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
Рассмотрим как эти два сценария обрабатывают все возможные ситуации. При начальной установке сценарий config задаёт вопросы и новый файл настройки генерируется сценарием postinst. При обновлении или перенастройке файл настройки читается и его значения используются для изменения значений в базе данных debconf, поэтому значения, изменённые администратором, не теряются. Вопросы задаются снова (могут показываться, а могут и нет). Затем сценарий postinst выполняет подстановку значений обратно в файл настройки, не изменяя всего остального.
Некоторые вещи ещё сильнее разочаровывают при использовании систем типа debconf: после заданного вопроса и ответа на него, переходишь к другому экрану с новым вопросом, и отвечая понимаешь, что совершил ошибку в последнем вопросе и хочешь вернуться обратно и обнаруживаешь, что не можешь сделать этого.
Так как debconf управляется вашим сценарием config, он не может прыгнуть обратно на предыдущий вопрос сам, но с небольшой вашей помощью, он сможет выполнить этот подвиг. Первый шаг — в сценарии config дать понять debconf, что сценарий config способен обрабатывать нажатие кнопки назад пользователем. Для этого используйте команду CAPB, передав backup в качестве параметра.
Затем, после каждой команды GO вы должны выполнять тест, чтобы увидеть просил ли пользователь вернуться назад (debconf возвратит код 30), и, если это произошло, возвратиться к предыдущему вопросу.
Есть несколько способов написания управляющих структур в вашей программе для возвращения к предыдущему вопросу при необходимости. Вы можете написать код, использующий кучу команд перехода goto. Или вы можете создать несколько функций и использовать рекурсию. Но возможно самым понятным и простым является создание конечного автомата. Вот скелет конечного автомата, который можно заполнить и расширить.
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
db_capb backup
STATE=1
while true; do
case "$STATE" in
1)
# Два
несвязных
вопроса.
db_input medium my/question || true
db_input medium my/other_question || true
;;
2)
# Задавать
этот
вопрос,
только
если
# на первый
был
получен
#
положительный
ответ.
db_get my/question
if [ "$RET" = "true" ]; then
db_input medium my/dep_question || true
fi
;;
*)
# Действие
по
умолчанию
возникает,
когда $STATE
больше чем
последнее
# введённое
состояние
и
прерывает
цикл. Для
# этого
требуется,
чтобы
состояния
были
пронумерованы
последовательно
с 1
# без
перерывов,
так как в
этом
случае
возникает
событие по
умолчанию
break # выход из
обёртывающего
цикла "while"
;;
esac
if db_go; then
STATE=$(($STATE + 1))
else
STATE=$(($STATE - 1))
fi
done
if [ $STATE -eq 0 ]; then
#
Пользователь
хочет
выйти из
первого
вопроса.
# Это
проблематичный
случай.
Обычная
установка
# пакетов с
помощью dpkg и apt
не даёт
# вернуться
к вопросам
между
пакетами
как здесь
написано,
# поэтому
завершить
работу,
оставив
пакет
ненастроенным,
# вероятно,
лучший
путь
обработки
этой
ситуации.
exit 10
fi
Заметим, что если ваш сценарий config задаёт несколько несвязных между собой вопросов, то конечный автомат не нужен. Просто задайте их все и GO; debconf покажет их все на одном экране, и пользователю не нужно возвращаться назад.
Это может произойти с debconf, если в сценарии config есть цикл. Предположим, вы задаёте вопрос и проверяете ответ, и всё это в цикле пока ответ не станет правильным:
ok=”
do while [ ! "$ok" ];
db_input low foo/bar || true
db_go || true
db_get foo/bar
if [ "$RET" ]; then
ok=1
fi
done
На первый взгляд всё выглядит хорошо. Но посмотрим что произойдёт, если значение foo/bar будет "" в начале цикла, а пользователь установил приоритет на высокий, или использует не интерактивный интерфейс, и поэтому вопрос на самом деле задан не будет. Значение foo/bar не изменяется в db_input, и тест не проходит и повторяется. И всё зацикливается …
Одним вариантом исправления является задание значения foo/bar перед входом в цикл. Например, если значение по умолчанию foo/bar равно «1», то вы можете выполнить RESET foo/bar перед входом в цикл.
В другом варианте можно проверить код завершения команды INPUT. Если он равен 30, то пользователю вопрос показан не был, и вы должны прервать цикл.
Иногда может выполняться установка похожих по функциональности пакетов, и вы хотели бы предложить пользователю выбрать пакет, который должен использоваться по умолчанию. Примером таких наборов могут быть оконные менеджеры или файлы словарей ispell.
Хотя можно для каждого пакета задавать простой вопрос «Использовать этот пакет по умолчанию?», но это приведёт к большому числу повторяющихся вопросов, если устанавливается несколько пакетов. С помощью debconf возможно создать список всех пакетов и позволить пользователю сделать из него выбор. Посмотрим как это делается.
Сделайте так, чтобы все пакеты в наборе использовали общий шаблон. Например:
Template: shared/window-manager
Type: select
Choices: ${choices}
Description: Выбор
оконного
менеджера
по
умолчанию.
Определяет
выбранный
оконный
менеджер,
который
запускается
по
умолчанию
при
запуске X.
Каждый пакет должен содержать копию этого шаблона. Также нужно включить код в свой сценарий 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
Объяснение. Во время запуска сценария config, debconf уже прочитал все шаблоны для устанавливаемых пакетов. Так как эти пакеты используют общий вопрос, debconf записывает этот факт в поле владельцев. По странному совпадению формат поля владельцев такой же как и у поля выбора (запятая и пробел являются разделителями в списке значений).
Команда METAGET может использоваться для получения списка владельцев и списка выбора. Если они различаются, то это значит, что был установлен новый пакет. Поэтому используется команда SUBST для замены списка выбора на список владельцев и задаётся вопрос.
При удалении пакета вы вероятно хотите проверить не является этот пакет выбранным в списке, и если так, то попросить пользователя выбрать другой пакет по умолчанию на замену.
Это можно выполнить добавив следующее в сценарии prerm всех похожих пакетов (заменив <package> именем пакета):
if [ -e /usr/share/debconf/confmodule ]; then
. /usr/share/debconf/confmodule
# больше не
задавать
этот
вопрос.
db_unregister shared/window-manager
# Проверить,
что общий
вопрос ещё
существует.
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
# Теперь
сделать
тоже что
делает
сценарий postinst
# для
обновления
символической
ссылки
оконного
менеджера.
fi
fi
В настоящее время debconf не полностью интегрирован с dpkg (но я хочу изменить это в будущем), и поэтому сейчас вызывается для некоторых неприятных хаков.
Худшие из них требуют запуска сценария config. Для этого в настоящий момент приходится запускать сценарий config во время предварительной настройки пакета. Также, при запуске сценария postinst, снова запускается debconf. Debconf понимает, что запускается из сценария postinst и поэтому останавливается и запускает сценарий config. Это работает, только если ваш postinst загружает хотя бы одну из библиотек debconf, поэтому postinst всегда делает это. Мы надеемся вернуться к этому позже добавив явную поддержку в dpkg для debconf. Программа debconf(1) — это шаг в данном направлении.
Похожий хак — запуск debconf когда сценарии config, postinst или другие программы используют его при запуске. Не смотря ни на что, они ожидают что будут сразу общаться с debconf. Сейчас это выполняется, так что когда такой сценарий загружает библиотеку debconf (типа /usr/share/debconf/confmodule), а debconf ещё не запущен, он запускается, и новая копия сценария выполняется заново. Заметный результат в том, что вам нужно указывать строку загрузки библиотеки debconf как можно ближе к началу сценария, или могут случиться непонятные вещи. Мы надеемся вернуться к этой проблеме позже изменив вызов debconf, и превратить его в что-то подобное отдельного демона.
Сравнимо с хаком и то, как debconf выясняет какие файл шаблонов загружены и когда их загружать. Когда сценарии config, preinst и postinst вызывают debconf, он автоматически выясняет где файл templates и загружает его. Отдельные программы, использующие debconf, заставляют debconf искать файл шаблонов в /usr/share/debconf/templates/имя_программы.templates. И если postrm хочет использовать debconf при вычистке, шаблоны будут недоступны если только у debconf не будет шанса загрузить их в postinst. Не неприятно, но неизбежно. Хотя в будущем некоторые из таких программ смогут использовать debconf-loadtemplate вручную.
Исторически сложившееся поведение /usr/share/debconf/confmodule играть с файловыми дескрипторами и устанавливать fd #3 через который происходит общение с debconf, может вызывать весь набор проблем при запуске из postinst демона, так как демон завершает общение с debconf, а debconf не может определить когда завершился сценарий. Команда STOP помогает обойти это. В будущем, мы рассмотрим создание связи с debconf через сокет или другой механизм отличный от stdio.
Debconf устанавливает DEBCONF_RECONFIGURE=1 перед запуском сценариев postinst, поэтому сценарий postinst, которому требуется избежать некоторой затратной операции перед перенастройкой, может проверить наличие этой переменной. Это хак, так как правильно сделать это — передать $1 = «reconfigure», но этого делать нельзя, так как будут работать неправильно все сценарии postinst, использующие debconf. Разработан план перехода на приём сценариями postinst значения «reconfigure», и как только все сделают это, начнётся передача этого параметра.
В debconf(7) содержится руководство пользователя debconf.
Описание debconf в политике debian является спецификацией протокола debconf. /usr/share/doc/debian-policy/debconf_specification.txt.gz
debconf.conf(5) содержит много полезной информации, включая описание среды хранения базы данных.
Joey Hess <joeyh@debian.org>