鵜飼文
敏*1
___________________________________________________________________________________________________________________________
debconf とは、 Debian においてパッケージの設定を行なうためのフレームワークおよびそれを実装したパッケージで す 。 そ も そ も は 、 元 Debian Project Leader の Wichert Akkerman 発案の configuration database framework 構想*2 であり 、 debconf は、 それに基づく Joey Hess による実装です。
従 来 、 パ ッケ ー ジ の 設 定 の う ち 、 パ ッケ ー ジ メ ン テ ナ が デフォルトを決めにくい もの、 つまりシステム管理者によって決定されるようなものは、 メンテナスクリプ ト*3 で、 プロンプトを だ し 管 理 者 が 入 力 し た 値 に 基 づ い て 設 定 フ ァイ ル を 生 成 す る よ う に し て い ま し た 。 こ れ は こ れ で 非 常 に 柔 軟 性 が 高 い*4 のですが、 パッ ケージによって*5 や り か た が 異 な って し ま い 、 デ ィス ト リ ビ ュー シ ョン と し て の 統 一 感 に 欠 け て し ま う と い う 欠 点 が あ り ま した。 また、 パッケージのインストール時・アップグレード時に常に管理者の介在が必要になってしまう た め に 、 イ ン ス ト ー ル ・ア ップ グ レ ー ド 中 に コ ン ソ ー ル を 離 れ て い る わ け に は い か な い と い う 問 題もはら んでいます。
そこで考案されたのが debconf です。 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 |
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 以外で設定ファイルを変更された場合も、 その情報を上書きすることなく反映する必要があり ます。
|
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 パッケージがインストールされる前 に*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 コマンドは以下のとおり
まず/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 変数名
|
また、 変数を新たにつくった場合は質問のメッセージの一部を変えることが多いでしょ う*16 。 そのために db_subst というのが使えます。 テンプレートの中で ${鍵文字列}というのを埋めこんでおい て、 次のように db_subst を実行すると、 ${鍵文字列}の部分が、 “置換文字列” に置きかえられ ます。
Template: mypackage/baz
... Description: ${鍵文字列} の値? ${鍵文字列}の値を入力してください |
db_register mypackage/baz mypackage/baz2
db_subst 変数名 鍵文字列 置換文字列 |
...
Description: 置換文字列 の値? 置換文字列の値を入力してください |
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 コマンドは以下のとおり
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 の入力として渡すとロードすることができます。 *18
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 が成功を意味*19 し、 critical が debconf/priority の値*20 を 意味します。
本文書では Debian で設定データの管理を司っている debconf について解説しました。
東 京 エ リ ア Debian 勉強会 2005 夏_________________________________________________________