玩式草子─ソフトウェアとたわむれる日々

第42回 Plamo Linuxのビルドスクリプトとパッケージ管理ツール[その4]

この記事を読むのに必要な時間:およそ 4.5 分

前回はニュース速報的にPlamo Linux 5.0リリースの話題を取りあげましたが,今回はPlamo Linuxのパッケージ管理の話題に戻り,前々回に紹介し残したinitpkgの機能について紹介しましょう。

パッケージの初期化問題

以前,Plamo Linuxがパッケージ形式として採用しているtgz/txz形式は,パッケージ用の機能を考慮した形式ではなく,インストールすべきファイルをtarでまとめて圧縮しただけだ,という話をしました。

一方,インストール時に,必要なファイルを適切な場所に置く以上の処理を必要とするソフトウェアもあります。たとえば,デーモンとして常駐するタイプのソフトウェアでは,セキュリティの観点から,専用のユーザアカウントを作って,その権限でしか動作しないように設計されていることがよくあります。

そのようなソフトウェアをパッケージとしてインストールするには,必要なユーザアカウントが既に存在するかを確認し,無ければ作成しなければなりません。パッケージ用として考慮されていないtgz/txz形式の場合,このような処理にも工夫が必要です。

先に紹介したように,tgz/txz形式の場合,tarで固めたパッケージを展開後,そのパッケージにinstall/doinst.shというスクリプトが含まれていれば,シェルスクリプトとしてそれを実行する,という機能があります。そこで,必要な処理をこのスクリプトに組み込む方法が考えられますが,ユーザアカウントを追加する操作を単に組み込むだけではうまく行きません。

というのも,Plamo Linuxも含め,たいていのLinuxディストリビューションでは,DVD等から起動されたインストーラ環境は,RAMディスクをルートディレクトリとする独立したLinux環境として動作しているので,インストール先の環境(HDD上のパーティション)からuseradd等のコマンドを発行しても,それは動作中のインストーラ環境に反映されてしまい,/mnt等にマウントされたインストール先の環境には反映されません。

また,コマンドやライブラリのパスはインストーラ環境を向いているので,そこには発行されたコマンドや必要なライブラリが存在しないこともあります。通常,インストーラ環境にはインストールに必要な最小限のコマンドしか用意されていないので,専用のコマンドを必要とする初期化処理は実行できないでしょう。

この種の問題を解決するには,インストール先の環境にchrootする方法が考えられます。chrootは,ファイルシステムの基点となるルートディレクトリを一時的に切り替えるコマンドで,インストール先の環境にchrootすれば,そこをルートディレクトリとして必要なコマンドやライブラリが検索されます。この機能を使えば,インストール先のバイナリファイルを起動して,インストール先の設定ファイルを書き変えることが可能です。

rpmやdeb形式のように,パッケージ自体が依存関係情報を持っていて,あるパッケージをインストールしようとすると,そのパッケージが依存しているパッケージも自動的にインストールされるような環境では,起動しようとするコマンドが必要とするライブラリもあらかじめインストールされているのでこの方法で十分でしょう。

ところが,tgz/txz形式ではパッケージ自体に依存関係情報を記録できないので,それぞれのパッケージは依存関係の有無に関わらずにインストールされます。その結果,あるパッケージのコマンドを動かそうとしても,それに必要なライブラリがまだインストールされていないことがあります。

このような問題を回避するために,Plamo Linuxではパッケージをカテゴリという単位に分けてインストールする順番を大まかに制御しているものの,GTKやQtを使うGUIツールの複雑な依存関係までは制御しきれていません。

initpkgの仕組み

そのためPlamo Linuxでは,パッケージごとにchrootしてコマンドを実行する方法は取らず,その種の配慮が必要なコマンドは,インストールした環境を最初に起動した時に実行することにしました。

具体的には,インストールに使う/sbin/installpkgコマンドを改造し,install/doinst.shスクリプト中に"%% begin"で始まる行があれば,そこから"%% end"までの部分を切り出して/var/initpkg/以下に保存し,installpkgではdoinst.shの残りの部分のみを実行するようにしました。

一方,/var/initpkg/以下に切り出した部分を実行するのは/etc/rc.d/rc.initpkgというスクリプトです。このスクリプトは,システムの起動時に/etc/rc.d/rc.Mから呼び出されるので,/var/initpkg/以下に切り出した部分の処理が実行されるのは,インストールが終了して初めて起動する時になります。

この処理の具体的な例として,gtk+_2-2.24.13-x86_64-P1.txzのinstall/doinst.shを見てみましょう。


 1  ( cd usr/lib64 ; rm -rf libgdk-x11-2.0.so.0 )
 2  ( cd usr/lib64 ; ln -sf libgdk-x11-2.0.so.0.2400.13 libgdk-x11-2.0.so.0 )
 3  ( cd usr/lib64 ; rm -rf libgdk-x11-2.0.so )
 4  ( cd usr/lib64 ; ln -sf libgdk-x11-2.0.so.0.2400.13 libgdk-x11-2.0.so )
 5  ( cd usr/lib64 ; rm -rf libgtk-x11-2.0.so.0 )
 6  ( cd usr/lib64 ; ln -sf libgtk-x11-2.0.so.0.2400.13 libgtk-x11-2.0.so.0 )
 7  ( cd usr/lib64 ; rm -rf libgtk-x11-2.0.so )
 8  ( cd usr/lib64 ; ln -sf libgtk-x11-2.0.so.0.2400.13 libgtk-x11-2.0.so )
 9  ( cd usr/lib64 ; rm -rf libgailutil.so.18 )
10  ( cd usr/lib64 ; ln -sf libgailutil.so.18.0.1 libgailutil.so.18 )
11  ( cd usr/lib64 ; rm -rf libgailutil.so )
12  ( cd usr/lib64 ; ln -sf libgailutil.so.18.0.1 libgailutil.so )
13  #%% begin initialize 
14  gtk-query-immodules-2.0 > /etc/gtk-2.0/gtk.immodules
15  #%% end

installpkgは,パッケージを展開後,このファイルを調べ,13行目から15行目の部分を/var/log/initpkg/gtk+_2というファイルに切り出してから,残りの1行目から12行目までのシンボリックリンク作成処理を実行します。

DVD等から起動した新規インストールの場合,切り出された部分はそのまま放置されます。そして,新しくインストールした環境が初めて起動した際,システムの起動スクリプトの一部である/etc/rc.d/rc.initpkgから実行されて,そこで必要な初期化処理が実行されるわけです。

新規インストールではなく,既存の環境にパッケージを追加インストールする場合は,システムの再起動を待たずに,/sbin/installpkgが直接rc.initpkgを呼び出して,パッケージのインストール直後に必要な処理を行うようにしています。

Plamo Linuxでは,install/doinst.shをインストールスクリプトと呼んでおり,それと区別する必要がある場合,この"#%% begin"から"#%% end"で括られた部分をinitpkgスクリプトと呼んでいます。

rc.initpkgから実行されたinitpkgスクリプトは,正常終了すれば/var/log/initpkg.log/へ移されます。正常に終了しなかった場合はそのまま/var/log/initpkg/に残され再度rc.initpkgが起動した際に実行が試みられます。

追加インストールの場合,パッケージをインストールする順番によってはinitpkgスクリプト実行時に必要なライブラリが揃っていないことがあります。そのため,必要なライブラリが無い等の理由で失敗したスクリプトは,他のパッケージをインストールする度に繰り返し実行され,必要なライブラリが揃って実行が無事完了すれば,その時点で/var/log/initpkg.log/へ移されるわけです。

このような仕様のため,手動でパッケージをインストールする場合,足りないライブラリがあったりすると,initpkgスクリプトが残ったままになって,新しいパッケージのインストールやシステムの起動のたびにエラーメッセージが表示される,という状態になることがあります。このような場合は/var/log/initpkg/に残っているファイルをチェックして,必要なライブラリ等を追加するようにしてください。

実行が終了したinitpkgスクリプトは/var/log/initpkg.log/に移されているので,それぞれのパッケージがどのような初期化処理を行ったのかも簡単に確認できます。

たとえば,各種スキャナを操作するsane_backendsパッケージの初期化処理は,/var/log/initpkg.log/sane_backendsに記録されており,以下のような,⁠scannerグループがあるかをチェックして,無ければ新しく作る⁠といった内容になっています。

1 #%% begin initialize 
2 grp_chk=`grep scanner /etc/group`
3 if [ "$grp_chk.x" = ".x" ]; then
4    echo "adding scanner group"
5    groupadd -g 46 scanner
6 fi
7 #%% end

このディレクトリには,他にもさまざまなパッケージの初期化処理が記録されているので,興味ある人は調べてみてください。

著者プロフィール

こじまみつひろ

Plamo Linuxとりまとめ役。もともとは人類学的にハッカー文化を研究しようとしていたものの,いつの間にかミイラ取りがミイラになってOSSの世界にどっぷりと漬かってしまいました。最近は田舎に隠棲して半農半自営な生活をしながらソフトウェアと戯れています。

URLhttp://www.linet.gr.jp/~kojima/Plamo/index.html

コメント

コメントの記入