鵜飼文
敏*2
_________________________________________________________________________________________________________________________________________________
debconf とは、 Debian においてパッケージの設定を行なうためのフレームワークおよびそれを実装したパッケージです。 そも そもは、 元 Debian Project Leader の Wichert Akkerman 発案の configuration database framework 構 想*3 であ り、 debconf は、 それに基づく Joey Hess による実装です。
従来、 パッケージの設定のうち、 パッケージメンテナがデフォルトを決めにくいもの、 つまりシステム管理者によって決定されるようなものは、 メンテナスクリプト*4 で、 プロンプトをだし管理者が入力した値に基づいて設定ファイルを生成するようにしていました。 これはこれで非常に柔軟性が高 い*5 のですが、 パッ ケージによって*6 やりかたが異なってしまい、 ディストリビューションとしての統一感に欠けてしまうという欠点がありまし た。 また、 パッケージのインストール時・アップグレード時に常に管理者の介在が必要になってしまうため に、 インストール・アップグレード中にコンソールを離れているわけにはいかないという問題もはらんでい ま す 。
そこで考案されたのが debconf です。 debconf を使うことで設定データを統一して扱うことができるようになり ます。
apt-utils をインストールしておくと apt-extracttemplates を使って、 パッケージをダウンロードしてインストール作業をする 前*7 に debconf を使ってパッケージの設定をおこなうことができるようになります。 この時は debconf 自体の設定 debconf/frontend に従ったフロン トエンド*8 を つかってユーザとのやりとりがおこなわれます。 また、 設定には優先度 (priority) *9がつけ られており、 debconf/priority の値より優先度が高いものだけがフロントエンドを介してユーザとやりとりをおこなわれるよ うになります。
またインストールした後も dpkg-reconfigure でパッケージの設定をしなおすことができます。 dpkg-reconfigure は、 debconf/priority の値にか かわらず低優先度 (low)*10 以 上すなわちすべての設定をやりなおすようになっています。
また、 現在そのパッケージの設定値がどうなっているかを知りたい場合は debconf-show コマンドが使え ます。
# debconf-show debconf
* debconf/priority: critical * debconf/frontend: Dialog |
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 スクリプトで設定情報を決定し*13 、 postinst スクリプトでそれを読みだして実際のパッケージの設定ファイルなどに書きだすという処理をおこなうことになり ます。
なお、 debconf データベースは registry として使う な*14 の で、 debconf データベースを参照するのはメンテナスクリプトだけにしておく必要があります。 また、 debconf 以外で設定ファ イルを変更された場合も、 その情報を上書きすることなく反映する必要があります。
|
debconf では、 メンテナスクリプトと debconf データベース間のやりとりのプロトコルを決めています。 こうすることで、 フロントエンドをかえたりバックエンドのデータベースの実装を変更したりすることができるようになっているわけ です。
debconf では templates ファイルでテンプレートを定義し、 そのテンプレートで作られる変数に対して debconf プロトコルを 使って値を設定したり、 読みだしたりしています。 テンプレートを定義するとそれと同名の変数がつくられるので、 ほとんどの 場合ではテンプレート名と同名の変数を使うことがほとんどですが、 同じような情報をいくつか持ちたい場合などではテンプ レートから複数の変数を生成する場合があります。
テンプレートは debian/templates ファイルもしくは debian/パッケージ名.templates ファイルに記述し ます。
Template: 名前 Type: 型 Default: デフォルト値 Description: 短かい説明 長い説明 |
名前としては基本的には「パッケージ名/識別子」 という文字列を使います。 パッケージ名がプレフィクスについているので、 他のパッケージのテンプレートと衝突することはありません。 もし複数のパッケージで共有するようなテンプレートは「share/ 共有名/識別子」 のような名前をつかうことが推奨されています。
型としては次のようなものがあります。
|
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-arch、 binary-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 です。
config スクリプトは、 deb パッケージがインストールされる前 に*15 実 行されます。 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 コマンドは以下のとおり
まず/usr/share/debconf/confmodule を. でよみこみます。 これで frontend と backend のプロセスにわかれ それぞれ通信するようになります。 ちなみに frontend は perl で書かれていて open2 でスクリプトを起動しな おして通信しています。 なお debconf シェルモジュールではすべてのコマンドには db_ が前についてるが、 プ ロトコル上はこの db_ は実際にはつけません。
通信に使う debconf プロトコルのバージョンをネゴシエーションします。 これは「version 2.0 で通信したい」 といっているわけで、 それが debconf でサポートできないようなバージョンだとリターンコード 30 を変数 $RET にいれてかえします。 この場合エラーになるので sh -e によりここで実行が終了すます。 このコマンド は postinst なんかでも使います。
必要とするキャパビリティを要求します。 指定できるのは backup および multiselect のふたつ。 backup は前 の質問に戻るをサポート、 multiselect は複数のセレクトをできるようにする機能です。
もしあれば、 その値で db_set して、 debconf 変数の値に反映させます。
db_set 変数名 値
|
db_set はユーザとのやりとりは発生しません。
質問ダイアログを出すときのタイトルを設定します。
db_input プライオリティ 変数名 || true
|
もしプライオリティが debconf 設定のプライオリティより高ければ変数名に対応しているテンプレートを使ってユーザ にデータを入力させるようにする。 つまり db_input low だとその質問はあまり重要ではなく細かい設定がしたい人だけ がやればいいというような項目になります。 逆に db_input critical だとユーザが与えないとまともな設定ができないよ うな項目になります。
|
どのようにデータを入力するかはそのテンプレートにわりあてられている型によってかわります。
もしユーザに提示しなかったらエラーで$RET が 30 になります。 そのため通常は —— true として sh -e によりここで スクリプトが終了しないようにします。
なお、 db_input だけでは入力の指示をフロントエンドに送るだけで、 質問自体はまだおこなわれません。 実際にフロン トエンドがユーザにたずねるのは db_go を呼びだした時です。
db_input で与えられてきた「質問してよー」 というのを実際にユーザに提示します。 ここでダイアログがでてきてユー ザとやりとりすることになります。
debconf は一度、 db_input で入力した場合、 その変数の seen フラグを true に設定します。 このフラグの値を変更するには db_fset を使います。
db_fset 変数名 seen false
|
デフォルト値に戻したい場合は db_reset を使います。 これでテンプレートに記述されていたデフォルト値に戻すことができ ます。
db_reset 変数名
|
基 本 的 に は テ ン プ レ ー ト と 同 名 の 変 数 を 使 う こ と で 事 足 り る 場 合 が 多 い で す が 、 必 要 が あ れ ば テ ン プ レ ー ト か ら 新 しい変数 を作ったりすることができます。 変数をつくったりけしたりする操作は db_register、 db_unregister を使い ます。
db_register テンプレート 変数名
|
db_unregister 変数名
|
また、 変数を新たにつくった場合は質問のメッセージの一部を変えることが多いでしょ う*17 。 そ のために db_subst というのが使えます。 テンプレートの中で ${鍵文字列}というのを埋めこんでおいて、 次のように db_subst を実行すると、 ${鍵文字列}の部分が、 “置換文字列” に置きかえられます。
Template: mypackage/baz
... Description: ${鍵文字列} の値? ${鍵文字列}の値を入力してください |
db_register mypackage/baz mypackage/baz2
db_subst 変数名 鍵文字列 置換文字列 |
...
Description: 置換文字列 の値? 置換文字列の値を入力してください |
postinst スクリプト*18 で は 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 コマンドは以下のとおり
config スクリプトと同様、 まず/usr/share/debconf/confmodule を. でよみこみます。 注意すべきことは、 こ こでconfig スクリプトもまた実行されるということです。
db_get 変数名
|
db_get を実行すると、 変数名であらわされる変数に格納されている値を$RET にとりだすことができ ます。
ここで debconf の処理を終了させます。 これ移行、 標準入出力が使えるようになります。 たとえば invoke-rc.d などで起 動されるものがある場合、 メッセージを標準出力にだそうとするのでこの前に db_stop しておかなければいけま せん。
postinst では、 この例にあるように既存の設定ファイルをできるだけ維持しつつ、 更新された設定値だけをいれかえるよう にすることが期待されています。
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# |
debconf を使う前にまず/usr/share/debconf/confmodule を. でよみこみます。
db_purge でこのパッケージに属する debconf データを debconf データベースから削除します。
もう debconf は必要ないので stop します。
debconf は confmodule をソースすることで、 frontend に exec しています。 その中で confmodule を呼びだした script を open2 で起動して db_ コマンドを frontend との通信にして処理をおこなっています。
fd=3 にコマンドを出力すると、 frontend プログラムで解釈実行され結果がかえってきます。 その結果はスクリプトの標準入 力に与えられるので read で読みとってスペースの前がコマンドの終了コード、 スペースの後が$RET に格納される値となり ます。
スクリプトがおわると frontend はそれを検知してデータベースに書き出して終了となります。
debconf で設定したデータはどこにあるのでしょうか? この設定は/etc/debconf.conf に記述されています。
デフォルトでは /var/cache/debconf に次のようなファイルとして格納されています。
debconf データベースの内容は debconf-get-selections を使うとダンプすることができ ます。 この出力を debconf-set-selections の入力として渡すとロードすることができます。 *19
debconf-get-selections –installer で、 debian-installer で使って debconf データベースをとりだすことができ ます。
その他に debconf-copydb を使うことでデータベースファイルをコピーすることができます。
debconf を使ってるスクリプトのデバッグは簡単ではありません。 しかし基本は DEBCONF_DEBUG に値を設定してスクリ プトを実行すればいい場合が多いでしょう。
# DEBCONF_DEBUG=’.*’ /var/lib/dpkg/info/パッケージ.postinst configure 最後に設定されたバージョン
|
これでパッケージの設定する時の debconf の動きを追うことができます。 なお簡単にするために dpkg-reconfigure debconf で debconf フロントエンドを Readline などをにしておいた方がいいでしょう。
DEBCONF_DEBUG=’.*’ というのは DEBCONF_DEBUG=user、 DEBCONF_DEBUG=developer、 DEBCONF_DEBUG=db すべてを指定したのと同じ意味になります。
debconf-communicate を使うと、 debconf データベースと直接やりとりすることができます。 標準入力からコマンドを与え ると、 標準出力に結果をかえします。 コマンドは debconf シェルモジュールでつかうコマンドから db_ をとりのぞいたものに なることに注意しましょう。 例えば次のように使います。
# echo ’get debconf/priority’ | debconf-communicate
0 critical |
0 が成功を意味*20 し、 critical が debconf/priority の値*21 を 意味します。
本文書では Debian で設定データの管理を司っている debconf について解説しました。
東 京 エ リ ア Debian 勉強会 2005_________________________________________________________________