2 debconf

鵜飼文 *1      
___________________________________________________________________________________________________________________________

2.1 はじめに

debconf とは、 Debian においてパッケージの設定を行なうためのフレームワークおよびそれを実装したパッケージで す 。 そ も そ も は 、 元 Debian Project Leader Wichert Akkerman 発案の configuration database framework 構想*2 であり 、 debconf は、 それに基づく Joey Hess による実装です。

従 来 、 パ ッケ ー ジ の 設 定 の う ち 、 パ ッケ ー ジ メ ン テ ナ が デフォルトを決めにくい もの、 つまりシステム管理者によって決定されるようなものは、 メンテナスクリプ *3 で、 プロンプトを だ し 管 理 者 が 入 力 し た 値 に 基 づ い て 設 定 フ ァイ ル を 生 成 す る よ う に し て い ま し た 。 こ れ は こ れ で 非 常 に 柔 軟 性 が 高 *4 のですが、 パッ ケージによって*5 や り か た が 異 な って し ま い 、 デ ィス ト リ ビ ュー シ ョン と し て の 統 一 感 に 欠 け て し ま う と い う 欠 点 が あ り ま した。 また、 パッケージのインストール時・アップグレード時に常に管理者の介在が必要になってしまう た め に 、 イ ン ス ト ー ル ・ア ップ グ レ ー ド 中 に コ ン ソ ー ル を 離 れ て い る わ け に は い か な い と い う 問 題もはら んでいます。

そこで考案されたのが debconf です。 debconf を使うことで設定データを統一して扱うことができるよ うになります。

2.2 debconf を使っているパッケージの設定の仕方

apt-utils をインストールしておくと apt-extracttemplates を使って、 パッケージをダウンロードしてインストール作 業をする前*6 debconf を使ってパッケージの設定をおこなうことができるようになりま す。 この時は debconf 自体の設定 debconf/frontend に従ったフロントエン *7 つかってユーザとのやりとりがおこなわれます。 また、 設定には優先度 (priority) *8がつ けられており、 debconf/priority の値より優先度が高いものだけがフロントエンドを介してユーザとやり とりをおこなわれるようになります。

またインストールした後も dpkg-reconfigure でパッケージの設定をしなおすこ とができます。 dpkg-reconfigure は、 debconf/priority の値にかかわらず低優先度 (low)*9 以上 すなわちすべての設定をやりなおすようになっています。

また、 現在そのパッケージの設定値がどうなっているかを知りたい場合は debconf-show コマンドが使 えます。

 # debconf-show debconf
 * debconf/priority: critical
 * debconf/frontend: Dialog

2.3 debconf の裏側

apt-get がパッケージをダウンロードしてくると/etc/apt/apt.conf.d/70debconf というファイルにより dpkg-preconfigure -apt が実行されるようになります。

// Pre-configure all packages with debconf before they are installed.
// If you don’t like it, comment it out.
DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt || true";};

dpkg-preconfigure では、 apt-utils apt-extracttempaltes を使っているため、 apt-utils がインストー ルされていないと、 debconf の設定はこのタイミングではおこなわれません。

dpkg-preconfigure -apt に対して、 いまダウンロードしたパッケージのリストがわたされるので、 それ らから template をとりだして config スクリプトの実行をおこないます。

基本的には、 config スクリプトで設定情報を決定 *12 postinst スクリプトでそれを読みだして実際のパッケージの設定ファイルなどに書きだすという処理をお こなうことになります。

なお、 debconf データベースは registry として使う *13 で、 debconf データベースを参照するのはメンテナスクリプトだけにしておく必要があります。 また、 debconf 以外で設定ファイルを変更された場合も、 その情報を上書きすることなく反映する必要があり ます。






シェルコマンド 内容 データのむき 使う場所




db_version ”2.0” バージョンネゴシエーション




db_capb multiselect キャパビリティネゴシエーション




db_title タイトル タイトル文字列の設定 スクリプト→ユーザ config




db_stop debconf の停止 postinst, postrm




db_input プライオリティ変数名変数への入力 テンプレ→ユーザ→ DB config




db_go 入力の実行 config




db_get 変数名 変数のとりだし DB →スクリプト postinst




db_set 変数名値 変数の設定 スクリプト→ DB config




db_reset 変数名 変数の初期化 テンプレ→ DB




db_subst 変数名鍵置換 置き換え テンプレ (←スクリプト)config




db_fget 変数名フラグ フラグのとりだし DB →スクリプト




db_fset 変数名フラグ値 フラグの設定 スクリプト→ DB




db_metaget 変数名フィールド フィールドのとりだし テンプレ→スクリプト




db_register テンプレート変数名変数の生成 元テンプレ→テンプレ config




db_unregister 変数名 変数の削除 →テンプレ




db_purge データベースから削除 →テンプレ、 DB postrm





1: debconf コマンド

debconf では、 メンテナスクリプトと debconf データベース間のやりとりのプロトコルを決めています。 こうすることで、 フロントエンドをかえたりバックエンドのデータベースの実装を変更したりすることが できるようになっているわけです。

2.3.1 テンプレートと変数

debconf では templates ファイルでテンプレートを定義し、 そのテンプレートで作られる変数に対して debconf プロトコルを使って値を設定したり、 読みだしたりしています。 テンプレートを定義するとそれ と同名の変数がつくられるので、 ほとんどの場合ではテンプレート名と同名の変数を使うことがほとんど ですが、 同じような情報をいくつか持ちたい場合などではテンプレートから複数の変数を生成する場合が あります。

テンプレートは debian/templates ファイルもしくは debian/パッケージ名.templates ファイルに記述し ます。

Template:  名前
Type: 
Default:  デフォルト値
Description:  短かい説明
  長い説明

名前としては基本的には「パッケージ名/識別子」 という文字列を使います。 パッケージ名がプレフィク スについているので、 他のパッケージのテンプレートと衝突することはありません。 もし複数のパッケー ジで共有するようなテンプレートは「share/共有名/識別子」 のような名前をつかうことが推奨されてい ます。

型としては次のようなものがあります。




型名

意味



string

文字列



boolean

true false



select

Choices:に設定されている値から一つ (“, ” で区切る)



multiselect

select と違い複数選べる



note

Description:の内容を提示するだけ。 メールとしても送られる



text

Description:の内容を提示する



password

パスワード用。




2: テンプレートの Type

debconf で使うメッセージは翻訳する場合、 debconf-gettextize を使って debian/po/ディレクトリ以下 に各国語版の po ファイルを置けるように準備をします。

 % debconf-gettextize templates

  To complete conversion, you must:
    a. Check that new templates files contain all the localized fields
    b. Add po-debconf to Build-Depends or Build-Depends-Indep in debian/control
    c. Remove obsolete files:
         templates.old
    d. Edit debian/rules to generate the localized templates file, either
       with dh\_installdebconf or directly with po2debconf

このように templates ファイルを指示して debconf-gettextize を実行すると、 元の templates ファイル .old サフィックスがついたものに残され、 新しい templates ファイルが作られます。 新しい templates ファイルは、 翻訳すべきフィールドは _” がプレフィクスとしてつくようになります。 そし po ディレクトリに POTFILES.in templates.pot が生成されます。 翻訳する場合は、 templates.pot をロケール名.po にコピーして gettext を翻訳するのと同じようにして翻訳 していきます。 マルチパッケージで複数の templates ファイルがある場合は、 それをすべ debconf-gettextize 実行時に指示します。 古い templates.old は消してしまってかまいま せん。

このようにして作られる翻訳を deb パッケージにちゃんととりこめるようにするには、 まず debian/control Build-Depends(Build-Depends-Indep) po-debconf を追加し ます。

後は debian/rules binary-archbinary-indep ルールで dh_installdebconf dh_installdeb の直 前くらいに呼ぶようにしておけば後は dh_installdebconf がしかるべき処理をしてくれま す。 cdbs を使っている場合は include /usr/share/cdbs/1/rules/debhelper.mk すれば中で dh_installdebconf を実行してくれます。 また Depends: 行に$misc:Depends をいれるの を忘れないようにしましょう。 dh_installdebconf がしかるべき依存関係を設定してくれ ます。

L10N バグ (po 翻訳) を受けとった時は、 そのファイルを debian/po ディレクトリにしかるべき名前 ( ケール名.po) で置くだけで OK です。

2.3.2 config スクリプト

config スクリプトは、 deb パッケージがインストールされる前 *14 行されます。 config スクリプトでやるべきことは基本的には以下のような処理になります。

#!/bin/sh -e
# sample config
#
. /usr/share/debconf/confmodule
db_version 2.0
db_capb multiselect
if [ -f /etc/default/mypackage ]; then
  . /etc/default/mypackage
  db_set mypackage/foo "$FOOR"
  db_set mypackage/bar "$BAR"
  db_go
fi

db_title "My Package Configuration"
db_input low mypackage/foo || true
db_input low mypackage/bar || true
db_go

config スクリプトで使う debconf コマンドは以下のとおり

debconf は一度、 db_input で入力した場合、 その変数の seen フラグを true に設定します。 このフラグ の値を変更するには db_fset を使います。

db_fset  変数名 seen false

デフォルト値に戻したい場合は db_reset を使います。 これでテンプレートに記述されていたデフォルト 値に戻すことができます。

db_reset  変数名

基本的にはテンプレートと同名の変数を使うことで事足りる場合が多いですが、 必要があればテンプ レートから新しい変数を作ったりすることができます。 変数をつくったりけしたりする操作は db_registerdb_unregister を使います。

db_register  テンプレート  変数名
db_unregister  変数名

また、 変数を新たにつくった場合は質問のメッセージの一部を変えることが多いでしょ *16 そのために db_subst というのが使えます。 テンプレートの中で ${鍵文字列}というのを埋めこんでおい て、 次のように db_subst を実行すると、 ${鍵文字列}の部分が、 置換文字列に置きかえられ ます。

Template: mypackage/baz
...
Description: ${鍵文字列}  の値?
 ${鍵文字列}の値を入力してください
 db_register mypackage/baz mypackage/baz2
 db_subst  変数名  鍵文字列  置換文字列
...
Description:  置換文字列  の値?
  置換文字列の値を入力してください
2.3.3 postinst スクリプト

postinst スクリプト*17 debconf からデータをよみだして実際の設定ファイルを生成することが仕事となります。 debconf 以前 では postinst 自身が echo read コマンドなどをつかってユーザの入力をいれていたのをここでは debconf からとってくるようにするわけです。

#!/bin/sh -e
#  postinst
. /usr/share/debconf/confmodule

case "$1" in
 configure)
   db_get mypackage/foo
   FOO="$RET"
   db_get mypackage/bar
   BAR="$RET"
   if [ -f /etc/default/mypackage ]; then
     sed -e ’s/^FOO=.*/FOO="’"$FOO"’"/’ \
 -e ’s/^BAR=.*/BAR="’"$BAR"’"/’
< /etc/default/mypackage > /etc/default/mypackage.dpkg-tmp
     if cmp -s /etc/default/mypackage /etc/default/mypackage.dpkg-tmp; then
   rm -f /etc/default/mypackage.dpkg-tmp
     else
   mv -f /etc/default/mypackage /etc/default/mypackage.dpkg-old
   mv /etc/default/mypackage.dpkg-tmp /etc/default/mypackage
     fi
   else
     cat <<DEFAULT > /etc/default/mypackage
# mypackage configuration file
# see /usr/share/doc/mypackage/README.Debian.
# this file is automatically managed by debconf.
#
# FOO="..."
#  foo is blah blah
FOO="$FOO"
#
# BAR="..."
#  bar is blah blha
BAR="$BAR"
# END OF FILE
DEFAULT
   fi
   ;;
 abort-upgrade|abort-remove|abort-deconfigure)
   ;;
 *)
   echo "postinst called with unknown argument ‘$1’" >&2
   exit 1
   ;;
esac
db_stop
#DEBHELPER#
exit 0

config スクリプトで使う debconf コマンドは以下のとおり

postinst では、 この例にあるように既存の設定ファイルをできるだけ維持しつつ、 更新された設定値だ けをいれかえるようにすることが期待されています。

2.3.4 postrm スクリプト

postrm スクリプトでは、 このパッケージの debconf データを debconf データベースから削除しておく必 要があります。

#!/bin/sh -e
#

case "$1" in
 purse
   . /usr/share/debconf/confmodule
   db_purge
   db_stop
   ;;
 remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disapper)
   ;;
 *)
   echo "$0 called with unknown argument ‘$1’" >&2
   exit 0
   ;;
esac
#DEBHELPER#
2.3.5 debconf プロトコルのやりとり

debconf confmodule をソースすることで、 frontend exec しています。 その中で confmodule を呼び だした script open2 で起動して db_ コマンドを frontend との通信にして処理をおこなってい ます。

fd=3 にコマンドを出力すると、 frontend プログラムで解釈実行され結果がかえってきます。 その結果 はスクリプトの標準入力に与えられるので read で読みとってスペースの前がコマンドの終了コード、 ス ペースの後が$RET に格納される値となります。

スクリプトがおわると frontend はそれを検知してデータベースに書き出して終了となり ます。

PIC

2.4 debconf データベース

debconf で設定したデータはどこにあるのでしょうか? この設定は/etc/debconf.conf に記述されてい ます。

デフォルトでは /var/cache/debconf に次のようなファイルとして格納されています。




ファイル名

内容



templates.dat

templates の情報



config.dat

設定データ



password.dat

パスワードデータ




4: debconf データベース

debconf データベースの内容は debconf-get-selections を使うとダンプすることができ ます。 この出力を debconf-set-selections の入力として渡すとロードすることができます。 *18

debconf-get-selections –installer で、 debian-installer で使って debconf データベースをとりだすことが できます。

その他に debconf-copydb を使うことでデータベースファイルをコピーすることができ ます。

2.5 debconf を使っているスクリプトのデバッグ

debconf を使ってるスクリプトのデバッグは簡単ではありません。 しかし基本は DEBCONF_DEBUG 値を設定してスクリプトを実行すればいい場合が多いでしょう。

 # DEBCONF_DEBUG=’.*’ /var/lib/dpkg/info/パッケージ.postinst configure  最後に設定されたバージョン

これでパッケージの設定する時の debconf の動きを追うことができます。 なお簡単にするために dpkg-reconfigure debconf debconf フロントエンドを Readline などをにしておいた方がいいで しょう。

DEBCONF_DEBUG=’.*’ というのは DEBCONF_DEBUG=userDEBCONF_DEBUG=developer DEBCONF_DEBUG=db すべてを指定したのと同じ意味になります。

debconf-communicate を使うと、 debconf データベースと直接やりとりすることができます。 標準入力 からコマンドを与えると、 標準出力に結果をかえします。 コマンドは debconf シェルモジュールでつかう コマンドから db_ をとりのぞいたものになることに注意しましょう。 例えば次のように使い ます。

 # echo ’get debconf/priority’ | debconf-communicate
 0 critical

0 が成功を意味*19 し、 critical debconf/priority の値*20 意味します。

2.6 おわりに

本文書では Debian で設定データの管理を司っている debconf について解説しました。

東 京 エ リ ア Debian 勉強会 2005 _________________________________________________________

PIC