Provided by: debconf-doc_1.5.26ubuntu3_all bug

НАЗВАНИЕ

       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 может быть запущен в трёх случаях:

       1      Во  время предварительной настройки пакета из dpkg-preconfigure,
              который запускает сценарий config с  параметрами  "configure"  и
              номером установленной версии.

       2      При   запуске  postinst  из  пакета,  debconf  также  попытается
              запустить сценарий config и передать те же параметры,  что  и  в
              случае  с предварительной настройкой пакета. Это необходимо, так
              как пакет может не  быть  предварительно  настроен,  и  сценарию
              config  даётся ещё одна попытка отработать. Подробней смотрите в
              разделе ХАКИ.

       3      При повторной настройке пакета с помощью  dpkg-reconfigure,  где
              сценарий   config  запускается  с  параметрами  "reconfigure"  и
              номером установленной версии.

       Заметим, что так как типичная установка или обновление  с  помощью  apt
       попадают  под  случаи 1 и 2, сценарий config обычно запускается дважды.
       Он ничего не должен делать во второй раз (отвечать  на  вопросы  второй
       раз  подряд  раздражает),  и  определённо  должен  быть идемпотентен. К
       счастью, debconf избегает повторения вопросов по умолчанию, поэтому это
       легко  достигается.

       Заметим,  что  сценарий  config запускается перед распаковкой пакета. В
       нём  должны   использоваться   только   команды   из   пакетов   первой
       необходимости.   Единственная   зависимость   пакета,   которая   будет
       удовлетворена до запуска сценария config -- это сам  debconf  (возможно
       указать версию).

       Сценарию  config ничего не нужно изменять в файловой системе. Он должен
       просто проверить состояние системы и задать вопросы, а debconf сохранит
       ответы,   которые  требуют  действий  позже  из  сценария  postinst.  И
       наоборот, сценарий postinst не должен использовать debconf для  задания
       вопросов,  а  вместо  этого должен полагаться на ответы, полученные при
       работе сценария config.

ФАЙЛ TEMPLATES

       Пакету, использующему  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 в  этом
       каталоге.

       Давайте рассмотрим каждое из полей по очереди..

       Template
              Название  шаблона в поле 'Template' обычно начинается с названия
              пакета.  Далее  можно  использовать  что   угодно;   вы   можете
              использовать   простую   схему  как  в  предыдущем  примере  или
              настроить "подкаталоги", содержащие похожие вопросы.

       Type   Тип  шаблона,  который  определяет  какого  вида  будет  показан
              элемент. Поддерживаются:

              string Поле  ввода  произвольных  данных, в которое пользователь
                     может ввести любую строку.

              password
                     Предлагает  пользователю  ввести  пароль.  Используйте  с
                     осторожностью;  этот  пароль будет сохранён в базу данных
                     debconf. Вероятно, вы должны удалить это значение из базы
                     как можно быстрее.

              boolean
                     Выбор true/false.

              select Выбор  одного из указанных значений. Значения должны быть
                     заданы в поле  'Choices'.  Разделителями  значений  могут
                     быть запятые и пробелы:
                       Choices: да, нет, может_быть

              multiselect
                     Как  и в типе данных select, выбор из списка, кроме того,
                     что пользователь может выбрать сразу  несколько  значений
                     из списка (или ни одного из них).

              note   Вместо  вопроса  как  такового,  этот  тип  данных задаёт
                     примечание, которое  может  быть  показано  пользователю.
                     Данный   тип  должен  использоваться  только  для  важных
                     сообщений,  которые   пользователи   обязательно   должны
                     увидеть,  так  как debconf обязательно сделает так, чтобы
                     пользователь увидел это; установка остановится,  пока  не
                     будет  нажата  клавиша.  Данный  тип  лучше  использовать
                     только для предупреждений о серьёзных проблемах.

              error  Этот тип данных используется для  сообщений  об  ошибках,
                     таких  как  ошибки  ввода  данных. Debconf покажет вопрос
                     этого  типа  даже  если   приоритет   самый   высокий   и
                     пользователь уже видел этот вопрос.

              title  Этот  тип  данных  используется  для  заголовков, которые
                     устанавливаются командой SETTITLE.

              text   Данный тип  данных  может  быть  использован  для  показа
                     частей    текста,   например   ярлыков,   которые   могут
                     использоваться   в   косметических   целях    отображения
                     некоторыми  интерфейсами.  Некоторые интерфейсы вообще не
                     используют  этот  тип.  Пока  нет  общих   принципов   по
                     использованию  его,  так  как  нет  интерфейсов,  которые
                     поддерживают его хорошо. Может в будущем он будет  вообще
                     удалён.

       Default
              Поле  'Default' указывает debconf, какое должно быть значение по
              умолчанию. Для  multiselect  это  может  быть  список  значений,
              разделённых  запятыми  или  пробелами, как в поле 'Choices'. Для
              select -- это одно значение из списка. Для boolean -- это "true"
              или  "false",  хотя  может  использоваться  любая  строка, и она
              игнорируется для паролей.

              Не подумайте, что поле значения по умолчанию содержит "ответ" на
              вопрос,  или  что он может быть использован для замены ответа на
              вопрос. Это не так, и не может быть так, он только предоставляет
              ответ  по  умолчанию  при  первом показе вопроса. Чтобы изменить
              значение по умолчанию на лету, используйте команду SET.

       Description
              Поле 'Description' подобно полю описания в пакете Debian,  имеет
              две  части:  короткое  описание и расширенное описание. Заметим,
              что  некоторые  интерфейсы  к  debconf  не  отображают   длинное
              описание,  или  могут  показать  его,  только  если пользователь
              попросит  показать  помощь.  Поэтому  короткое  описание  должно
              отображать всю суть вопроса.

              Если  вы  не  можете  придумать  длинного  описания,  то сначала
              подумайте  ещё  немного.  Напишите  в  debian-devel.   Попросите
              помочь.  Возьмите  урок  по  написанию!  Длинное  описание очень
              важно. Если после всего  этого  ничего  не  приходит  в  голову,
              оставьте  поле  пустым.  Нет  смысла  дублировать  то,  что  уже
              написано в коротком описании.

              Текст в расширенном описании будет переноситься по словам,  если
              он  не  начинается  с дополнительного пробельного символа (после
              первого  обязательного  пробела).  Вы  можете  разбить  его   на
              параграфы поместив " ." в пустой строке между параграфами.

ВОПРОСЫ

       Вопрос  --  это  проиллюстрированный  шаблон.  Прося  debconf  показать
       вопрос, таким образом ваш сценарий  config  может  взаимодействовать  с
       пользователем.  Когда  debconf загружает файл templates (это происходит
       при запуске сценария config или postinst), он автоматически  показывает
       вопрос   каждого  шаблона.  На  самом  деле  можно  показать  несколько
       независимых вопросов из одного шаблона (с помощью команды REGISTER), но
       это  требуется  редко.  Шаблоны  --  это  статические  данные  из файла
       templates, а вопросы используются  для  хранения  динамических  данных,
       таких  как  имеющийся  ответ  на вопрос, видел ли пользователь уже этот
       вопрос и тому подобное. Помните  об  этом  различии  между  шаблоном  и
       вопросом, но не стоит сильно забивать этим голову.

ОБЩИЕ ШАБЛОНЫ

       Фактически,  есть  возможность  иметь  один  шаблон  и вопрос сразу для
       нескольких пакетов. Все пакеты  могут  предоставлять  идентичную  копию
       шаблона  в  своих файлах templates. Это может быть полезно, если набору
       пакетов требуется задать один и тот же вопрос, а вы хотите побеспокоить
       пользователя  только  один  раз.  Общие  шаблоны  обычно  помещаются  в
       псевдокаталог shared/ в пространстве имён шаблонов debconf.

ПРОТОКОЛ DEBCONF

       Сценарии config взаимодействуют с debconf  по  протоколу  debconf.  Это
       простой однострочный протокол, похожий на основные протоколы интернета,
       типа SMTP. Сценарий config  посылает  debconf  команду,  записывая  эту
       команду в стандартный вывод. Затем, он может прочитать ответ debconf со
       стандартного ввода.

       Ответы debconf можно разделить на две части:  числовой  код  результата
       (первое  слово  в  ответе)  и необязательный расширенный код результата
       (оставшаяся часть ответа). В числовом  коде  значение  0  соответствует
       успешному  выполнению,  а  другие  числа  указывают  на различного вида
       неудачи.  Подробней  смотрите  таблицу  в   политике   Debian,   раздел
       спецификации debconf.

       Расширенный  код  результата имеет любой вид и никак не стандартизован,
       поэтому нужно игнорировать его  и  не  пытаться  использовать  в  своей
       программе  для  выяснения  что  делает  debconf.  Исключение составляют
       команды типа GET, которая создаёт значение для возврата  в  расширенном
       коде результата.

       Обычно  вы  будете  использовать библиотеку, которая работает на низком
       уровне для установления связи с debconf и взаимодействия с ним.

       А теперь обсудим команды протокола. Это  не  полное  описание,  за  ним
       обращайтесь к документу о политике Debian, раздел спецификации debconf.

       VERSION номер
              Обычно  не  нужно  использовать  эту  команду.   Она   позволяет
              договориться с debconf о том, какая версия протокола должна быть
              использована. Текущая версия протокола -- 2.0,  а  версии  ветки
              2.x обратно совместимы. Вы можете указать номер версии протокола
              и debconf вернёт версию протокола в расширенном коде результата.
              Если   указанная  вами  версия  слишком  стара,  debconf  вернёт
              числовой код 30.

       CAPB возможности
              Обычно  не  нужно  использовать  эту  команду.   Она   позволяет
              договориться  с  debconf  о  списке поддерживаемых возможностей.
              Будут использованы возможности, для которые есть поддержка  и  у
              вас  и у debconf, а debconf вернёт список всех поддерживаемых им
              возможностей.

              Если среди ваших возможностей будет 'escape', то  debconf  будет
              ожидать,  что в посылаемых вами командах символы обратный слеш и
              новой строки экранированы (\\ и \n соответственно),  а  в  своих
              ответах  будет  также  это  делать. Это может быть использовано,
              например, для подстановки многостроковых строк в  шаблонах,  или
              для получения многострочных расширенных описаний, использующихся
              в METAGET. В этом режиме вы  должны  сами  экранировать  входной
              текст    (для    этого    вы    можете    использовать   команду
              debconf-escape(1), если хотите), а библиотеки  confmodule  будут
              снимать экранирования в ответах за вас.

       TITLE строка
              Устанавливает     заголовок,    который    debconf    показывает
              пользователю. Обычно редко используется, так как  debconf  может
              автоматически генерировать заголовок из имени вашего пакета.

       SETTITLE вопрос
              Устанавливает   заголовок   к   краткому  описанию  шаблона  для
              определённого  вопроса.   Шаблон   должен   быть   типа   title.
              Преимущество  над  командой  TITLE  в  том,  что  это  позволяет
              заголовкам храниться в одном месте вместе с  вопросами  debconf,
              что даёт возможность переводить их на другой язык.

       INPUT приоритет вопрос
              Просит  debconf подготовить к показу вопрос пользователю. Вопрос
              не показывается до тех пор пока не будет дана  команда  GO;  это
              позволяет  последовательно  задать  несколько  команд  INPUT для
              накопления набора вопросов, которые могут быть заданы все  разом
              на одном экране.

              Поле  приоритета говорит debconf насколько важен вопрос, который
              будет показан пользователю. Значения приоритета:

              low    Очень  простые  элементы  со  значениями  по   умолчанию,
                     которые   работают  в  подавляющем  большинстве  случаев;
                     только параноики увидят их.

              medium Обычные элементы с корректными значениями по умолчанию.

              high   Элементы, у которых нет приемлемых значений по умолчанию.

              critical
                     Элементы, которые вероятно сломают систему, если не будет
                     вмешательства пользователя.

              Debconf  сам  решает  нужно   ли   вообще   показывать   вопрос,
              основываясь  на этом приоритете и том, видел ли уже пользователь
              этот вопрос и какой  интерфейс  используется  для  показа.  Если
              вопрос не будет показан, debconf возвращает код 30.

       GO
              Указывает debconf показать накопленные вопросы (переданные ранее
              командами INPUT) пользователю.

              Если поддерживается возможность backup и пользователь потребовал
              вернуться на шаг назад, то debconf возвратит код 30.

       CLEAR  Очистить  накопленные  вопросы (из команд INPUT) и не показывать
              их.

       BEGINBLOCK

       ENDBLOCK
              Некоторые интерфейсы debconf могут показывать пользователю сразу
              несколько вопросов одновременно. Может быть в будущем интерфейсы
              даже смогут группировать такие  вопросы  по  блокам  на  экране.
              BEGINBLOCK  и  ENDBLOCK  могут  указываться вокруг набора команд
              INPUT, чтобы обозначить  блоки  вопросов  (и  блоки  могут  быть
              вложенными).  Так  как  пока  ни  один  интерфейс  к  debconf не
              поддерживает их, в данный момент эти команды игнорируются.

       STOP   Эта команда указывает debconf  на  завершения  взаимодействия  с
              ним.   Часто  debconf  может  сам  обнаружить  завершение  вашей
              программы и эта команда не обязательна.

       GET вопрос
              После отработки  INPUT  и  GO  для  показа  вопроса,  вы  можете
              использовать  эту  команду  для  получения  значения  введённого
              пользователем. Значение возвращается в  виде  расширенного  кода
              результата.

       SET вопрос ответ
              Задаёт ответ на вопрос; это можно использовать для замены ответа
              по умолчанию чем-то,  что  ваша  программа  вычислила  во  время
              работы.

       RESET вопрос
              Сбрасывает  ответ на вопрос в значение по умолчанию (как указано
              в поле 'Default' в шаблоне).

       SUBST вопрос ключ значение
              Вопросы могут содержать  подстановки  в  полях  'Description'  и
              'Choices'  (хотя  использование  подстановок  в  полях 'Choices'
              считается хаком; со временем будет  разработан  лучший  способ).
              Эти   подстановки   выглядят   как   "${ключ}".   Когда   вопрос
              отображается, подстановки заменяются  на  нужные  значения.  Эта
              команда   может   быть   использована   для   задания   значения
              подстановки. Это полезно, если вам требуется  показать  какое-то
              сообщение  пользователю,  которое  нельзя  однозначно записать в
              файл templates.

              Не пытайтесь использовать SUBST для замены ответа  по  умолчанию
              на  вопрос;  это  не сработает, так как для этого служит команда
              SET.

       FGET вопрос флаг
              Вопросы могут иметь связанные с ними флаги.  Флаги  могут  иметь
              значение  "true"  или  "false".  Эта команда возвращает значение
              флага.

       FSET вопрос флаг значение
              Устанавливает значение флага вопроса. Значение должно  быть  или
              "true" или "false".

              Распространённым   флагом   является   флаг  "seen".  Обычно  он
              устанавливается  только  если  пользователь  уже  видел  вопрос.
              Debconf  обычно  показывает  только  те  вопросы пользователю, у
              которых флаг seen установлен  в  "false"  (или  если  происходит
              процесс   перенастройки   пакета).   Иногда   вам   нужно  чтобы
              пользователь увидел вопрос снова --  в  этом  случае  вы  можете
              установить флаг seen в значение "false", чтобы заставить debconf
              показать вопрос ещё раз.

       METAGET вопрос поле
              Возвращает значение  любого  поля  вопроса  из  соответствующего
              шаблона (например, Description).

       REGISTER шаблон вопрос
              Создаёт  новый  вопрос,  который  привязывается  к  шаблону.  По
              умолчанию, каждый шаблон имеет соответствующий вопрос с  тем  же
              именем. Однако, с шаблоном можно связать любое число вопросов, и
              это позволяет создать много таких вопросов.

       UNREGISTER вопрос
              Удаляет вопрос из базы данных.

       PURGE  Вызывайте эту команду из сценария postrm  при  вычистке  пакета.
              Она удалит все вопросы пакета из базы данных debconf.

       X_LOADTEMPLATEFILE /путь/к/templates [владелец]
              Это  расширение  загружает указанный файл template в базу данных
              debconf. По умолчанию, владельцем  считается  пакет,  который  в
              данный момент настраивается 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(3),  а   программисты   на   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

       В последнем разделе был  приведён  пример  сценария  postinst,  который
       использует   debconf   для  получения  ответа  на  вопрос  и  выполняет
       соответствующие действия. Есть несколько вещей о которых нужно  помнить
       при написании сценариев postinst, использующих debconf:

       *      Не  задавайте  вопросов  из  сценария  postinst.  Вопросы должен
              задавать сценарий config  с  помощью  debconf,  для  того  чтобы
              работал механизм предварительной настройки.

       *      Всегда  включайте  /usr/share/debconf/confmodule  в самом начале
              сценария postinst, даже если  не  будет  использоваться  никаких
              команд  db_*.  Это  нужно  для того, чтобы дать шанс запуститься
              сценарию config (подробней смотрите в разделе ХАКИ).

       *      Избегайте вывода чего-либо в stdout из  сценария  postinst,  так
              как  это  debconf  может  неправильно  понять и вообще, сценарий
              postinst не должен быть слишком разговорчивым. Если очень  нужно
              -- выводите в stderr.

       *      Если  сценарий  postinst запускается в режиме демона, убедитесь,
              что вы послали debconf команду STOP  в  конце  работы,  так  как
              debconf  не сможет отловить момент когда postinst закончил с ним
              работать.

       *      Пишите  сценарий  postinst  так,  чтобы   он   принимал   первым
              параметром   "reconfigure".   Он   может   трактовать   его  как
              "configure". Это будет использовано в следующих версиях debconf,
              чтобы  указать  сценариям  postinst  когда  они должны выполнять
              перенастройку.

ДРУГИЕ СЦЕНАРИИ

       Кроме сценариев 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,  ответ  на  вопрос  будет   автоматически   возвращён   на
       английский.

       You  will  find  it  easier  to manage translations if you keep them in
       separate  files;  one  file  per  translation.   In   the   past,   the
       debconf-getlang(1)  and debconf-mergetemplate(1)  programs were used to
       manage debian/template.ll  files.  This  has  been  superseded  by  the
       po-debconf(7)   package,  which lets you deal with debconf translations
       in .po files, just like any other translations. Your  translators  will
       thank you for using this new improved mechanism.

       For  the  details  on  po-debconf,  see  its  man page. If you're using
       debhelper, converting  to  po-debconf  is  as  simple  as  running  the
       debconf-gettextize(1)   command  once, and adding a Build-Dependency on
       po-debconf and on debhelper (>= 4.1.13).

СОБЕРЁМ ВСЁ ВМЕСТЕ

       Итак, у вас есть сценарий config, файл  templates,  сценарий  postinst,
       использующие  debconf  и  так  далее.  Поместить  все эти части в пакет
       debian  несложно.  Вы  можете  сделать  это  вручную  или   с   помощью
       dh_installdebconf(1), которая объединяет переведённые шаблоны, копирует
       файлы в нужные места, и даже генерирует  вызов  PURGE,  который  должен
       быть в сценарии postrm. Убедитесь, что ваш пакет зависит от debconf (>=
       0.5), так как более ранние  версии  несовместимы  с  всем  описанным  в
       руководстве. Всё.

       Да,  за  исключением  тестирования,  отладки  и реального использования
       debconf для более интересных вещей чем  простое  задание  вопросов.  Об
       этом читайте далее..

ОТЛАДКА

       Итак, у вас есть пакет, который предположительно использует debconf, но
       он не совсем работает. Может быть debconf не только задаёт вопросы  при
       настройке.  Или  может  быть  что-то  странное случается; он крутится в
       каком-то вечном цикле или хуже. К счастью, debconf обладает  множеством
       средств отладки.

       DEBCONF_DEBUG
              Наипервейшая  вещь  --  это  переменная окружения DEBCONF_DEBUG.
              Если вы  сделаете  export  DEBCONF_DEBUG=developer,  то  debconf
              будет  выводить  в stderr дамп протокола debconf при работе. Это
              выглядит как-то так(сразу видно опечатку):

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

              Для отладки  довольно  полезно  использовать  интерфейс  debconf
              readline(по  мнению  автора), поскольку вопросы не мешают и весь
              отладочный вывод легко сохранить.

       DEBCONF_C_VALUES
              If this environment variable is set to 'true', the frontend will
              display the values in Choices-C field (if present) of select and
              multiselect templates rather than the descriptive values.

       debconf-communicate
              Другим     полезным     инструментом     является      программа
              debconf-communicate(1).   Просто   запустите  её  и  вы  сможете
              интерактивно вводить команды протокола debconf непосредственно в
              debconf. Это отличный способ попробовать команды на лету.

       debconf-show
              Если   пользователь   сообщил  о  проблеме,  можно  использовать
              debconf-show(1), чтобы скопировать все вопросы пакета,  показать
              их ответы и узнать какие из них видел пользователь.

       .debconfrc
              Чтобы  избежать  утомительного  цикла  сборка/установка/отладка,
              можно загрузить файл templates с помощью debconf-loadtemplate(1)
              и   запустить   сценарий   config   вручную  с  помощью  команды
              debconf(1).   Однако,   вам   по   прежнему   требуются    права
              суперпользователя?  Не  очень  здорово.  И в идеале вы хотели бы
              увидеть как проходит новая  установка,  с  чистой  базой  данных
              debconf.

              Оказывается,  если  вы  настроите файл ~/.debconfrc для обычного
              пользователя, указав в нём личный config.dat и template.dat,  то
              сможете  загружать  файлы  templates и запускать сценарий config
              как хочется, без полномочий суперпользователя.  Если  нужно  ещё
              раз  запуститься  с  чистой  базой  данных, просто удалите файлы
              *.dat.

              Подробности настройки смотрите в debconf.conf(5), и заметим, что
              файл  /etc/debconf.conf  отлично подойдёт как шаблон для личного
              файла ~/.debconfrc.

УГЛУБЛЁННОЕ ПРОГРАММИРОВАНИЕ С DEBCONF

   Работа с файлами настройки
       Многие из вас хотели бы использовать  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)
                 # Two unrelated questions.
                 db_input medium my/question || true
                 db_input medium my/other_question || true
            ;;
            2)
                 # Only ask this question if the
                 # first question was answered in
                 # the affirmative.
                 db_get my/question
                 if [ "$RET" = "true" ]; then
                      db_input medium my/dep_question || true
                 fi
            ;;
            *)
                 # The default case catches when $STATE is greater than the
                 # last implemented state, and breaks out of the loop. This
                 # requires that states be numbered consecutively from 1
                 # with no gaps, as the default case will also be entered
                 # if there is a break in the numbering
                 break # exits the enclosing "while" loop
            ;;
            esac

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

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

       Заметим,  что если ваш сценарий 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-manage 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>

                                                              DEBCONF-DEVEL(7)