パッケージ管理についての説明を LFS ブックに加えて欲しいとの要望をよく頂きます。 パッケージ管理ツールがあれば、インストールされるファイル類を管理し、パッケージの削除やアップグレードを容易に実現できます。 パッケージ管理ツールでは、バイナリファイルやライブラリファイルだけでなく、設定ファイル類のインストールも取り扱います。 パッケージ管理ツールをどうしたら・・・ いえいえ本節は特定のパッケージ管理ツールを説明するわけでなく、その利用を勧めるものでもありません。 もっと広い意味で、管理手法にはどういったものがあり、どのように動作するかを説明します。 あなたにとって最適なパッケージ管理がこの中にあるかもしれません。 あるいはそれらをいくつか組み合わせて実施することになるかもしれません。 本節ではパッケージのアップグレードを行う際に発生する問題についても触れます。
LFS や BLFS において、パッケージ管理ツールについて触れていない理由には以下のものがあります。
本書の目的は Linux システムがいかに構築されているかを学ぶことです。 パッケージ管理はその目的からはずれてしまいます。
パッケージ管理についてはいくつもの方法があり、それらには一長一短があります。 ユーザーに対して満足のいくものを選び出すのは困難です。
ヒントプロジェクト (Hints Project) ページに、パッケージ管理についての情報が示されています。 それらが望むものかどうか確認してみてください。
パッケージ管理ツールがあれば、各種ソフトウェアの最新版がリリースされた際に容易にアップグレードができます。 全般に LFS ブックや BLFS ブックに示されている作業手順に従えば、新しいバージョンへのアップグレードを行っていくことはできます。 以下ではパッケージをアップグレードする際に注意すべき点、特に稼動中のシステムに対して実施するポイントについて説明します。
ツールチェーン (Glibc、GCC、Binutils) のいずれかについて、マイナーバージョンをアップグレードする必要がある場合は、LFS を再構築するのが無難です。 この場合、すべてのパッケージの依存関係を考慮して順番に作り直せば実現できるはず ですが、これはあまりお勧めしません。 例えば glibc-2.2.x を glibc-2.3.x にアップグレードする必要がある場合は、再構築するのが無難です。 マイクロバージョンをアップグレードする場合は、もっと単純にそのパッケージをインストールし直すだけで動作すると思いますが、保証はありません。 例えば glibc-2.3.4 を glibc-2.3.5 にアップグレードする場合、普通は何も問題ないでしょう。
共有ライブラリを提供しているパッケージをアップデートする場合で、そのライブラリの名前が変更になった場合は、そのライブラリを動的にリンクしているすべてのパッケージは、新しいライブラリにリンクされるように再コンパイルを行う必要があります。
(パッケージのバージョンとライブラリ名との間には相関関係はありません。) 例えば foo-1.2.3
というパッケージが共有ライブラリ libfoo.so.1
をインストールするものであるとします。 そして今、新しいバージョン foo-1.2.4 にアップグレードし、共有ライブラリ
libfoo.so.2
をインストールするとします。
この例では libfoo.so.1
を動的にリンクいるパッケージがあったとすると、それらはすべて libfoo.so.2
に対してリンクするよう再コンパイルしなければなりません。
古いライブラリに依存しているパッケージすべてを再コンパイルするまでは、そのライブラリを削除するべきではありません。
以下に一般的なパッケージ管理手法について示します。 パッケージ管理マネージャを用いる前に、様々な方法を検討し、特にそれぞれの欠点も確認してください。
そうです。 これもパッケージ管理のやり方の一つです。 いろいろなパッケージに精通していて、どんなファイルがインストールされるか分かっている人もいます。 そんな人はパッケージ管理ツールを必要としません。 あるいはパッケージが更新された際に、システム全体を再構築しようと考えている人なら、やはりパッケージ管理ツールを必要としません。
これは最も単純なパッケージ管理のやり方であり、パッケージ管理のためのツールを用いる必要はありません。
個々のパッケージを個別のディレクトリにインストールする方法です。 例えば foo-1.1 というパッケージを
/usr/pkg/foo-1.1
ディレクトリにインストールし、この
/usr/pkg/foo-1.1
に対するシンボリックリンク
/usr/pkg/foo
を作成します。
このパッケージの新しいバージョン foo-1.2 をインストールする際には /usr/pkg/foo-1.2
ディレクトリにインストールした上で、先ほどのシンボリックリンクをこのディレクトリを指し示すように置き換えます。
PATH
、 LD_LIBRARY_PATH
、 MANPATH
、 INFOPATH
、
CPPFLAGS
といった環境変数に対しては /usr/pkg/foo
ディレクトリを加える必要があるかもしれません。
もっともパッケージによっては、このやり方では管理できないものもあります。
これは一つ前に示したパッケージ管理テクニックの応用です。 各パッケージは同様にインストールします。
ただし先ほどのようなシンボリックリンクを生成するのではなく /usr
ディレクトリ階層の中に各ファイルのシンボリックリンクを生成します。 この方法であれば環境変数を追加設定する必要がなくなります。
シンボリック・リンクを自動生成することもできますが、パッケージ管理ツールの中にはこの手法を使って構築されているものもあります。
よく知られているものとして Stow、Epkg、Graft、Depot があります。
インストール時には意図的な指示が必要です。 パッケージにとっては /usr
にインストールすることが指定されたものとなりますが、実際には
/usr/pkg
配下にインストールされるわけです。
このインストール方法は単純なものではありません。 例えば今 libfoo-1.1 というパッケージをインストールするものとします。
以下のようなコマンドでは、このパッケージを正しくインストールできません。
./configure --prefix=/usr/pkg/libfoo/1.1 make make install
インストール自体は動作しますが、このパッケージに依存している他のパッケージは、期待どおりには libfoo
を正しくリンクしません。 例えば libfoo をリンクするパッケージをコンパイルする際には /usr/lib/libfoo.so.1
がリンクされると思うかもしれませんが、実際には
/usr/pkg/libfoo/1.1/lib/libfoo.so.1
がリンクされることになります。 正しくリンクするためには DESTDIR
変数を使って、パッケージのインストールをうまく仕組む必要があります。 この方法は以下のようにして行います。
./configure --prefix=/usr make make DESTDIR=/usr/pkg/libfoo/1.1 install
多くのパッケージは、たいていはこの手法をサポートしていますが、そうでないものもあります。
この手法を取り入れていないパッケージに対しては、手作業にてインストールすることが必要になります。
またはそういった問題を抱えるパッケージであれば /opt
ディレクトリにインストールする方が容易なことかもしれません。
この方法ではパッケージをインストールするにあたって、あるファイルにタイムスタンプが記されます。 インストールの直後に find コマンドを適当なオプション指定により用いることで、インストールされるすべてのファイルのログが生成されます。 これはタイムスタンプファイルの生成の後に行われます。 この方法を用いたパッケージ管理ツールとして install-log があります。
この方法はシンプルである利点がありますが、以下の二つの欠点があります。 インストールの際に、いずれかのファイルのタイムスタンプが現在時刻でなかった場合、そういったファイルはパッケージ管理ツールが正しく制御できません。 またこの方法は一つのパッケージだけが、その時にインストールされることを前提とします。 例えば二つのパッケージが二つの異なる端末から同時にインストールされるような場合は、ログファイルが適切に生成されません。
この方法はインストールスクリプトが実行するコマンドを記録するものです。 これには以下の二種類の手法があります。
環境変数 LD_PRELOAD
を使えば、インストール前にあらかじめロードされるライブラリを定めることができます。 パッケージのインストール中には
cp、 install、 mv
など様々な実行モジュールにそのライブラリをリンクさせ、ファイルシステムを変更するようなシステムコールを監視することで、そのライブラリがパッケージを追跡管理できるようになります。
この方法を実現するためには、動的リンクする実行モジュールはすべて suid ビット、sgid ビットがオフでなければなりません。
事前にライブラリをロードしておくと、インストール中に予期しない副作用が発生するかもしれません。
したがって、ある程度のテスト確認を行って、パッケージ管理ツールが不具合を引き起こさないこと、しかるべきファイルの記録を取っておくことが必要とされます。
二つめの方法は strace を用いるものです。 これはインストールスクリプトの実行中に発生するシステムコールを記録するものです。
この方法では、シンボリックリンク方式によるパッケージ管理にて説明したのと同じように、パッケージが個別のディレクトリにインストールされます。 インストールされた後には、インストールファイルを使ってアーカイブが生成されます。 このアーカイブはこの後に、ローカルPCへのインストールに用いられ、他のPCのインストールに利用することもできます。
商用ディストリビューションが採用しているパッケージ管理ツールは、ほとんどがこの方法によるものです。 この方法に従ったパッケージ管理ツールの例に RPM があります。 (これは Linux Standard Base Specification が規定しています。) また pkg-utils、Debian の apt、Gentoo の Portage システムがあります。 このパッケージ管理手法を LFS システムに適用するヒント情報が http://www.linuxfromscratch.org/hints/downloads/files/fakeroot.txt にあります。
パッケージファイルにその依存パッケージ情報まで含めてアーカイブ生成することは、非常に複雑となり LFS の範疇を超えるものです。
Slackware は、パッケージアーカイブに対して tar ベースのシステムを利用しています。 他のパッケージ管理ツールはパッケージの依存性を取り扱いますが、このシステムは意図的にこれを行っていません。 Slackware のパッケージ管理に関する詳細は http://www.slackbook.org/html/package-management.html を参照してください。
この手法は LFS に固有のものであり Matthias Benkmann により考案されました。 ヒントプロジェクト (Hints Project) から入手することが出来ます。 考え方としては、各パッケージを個々のユーザーが共有ディレクトリにインストールします。 パッケージに属するファイル類は、ユーザーIDを確認することで容易に特定出来るようになります。 この手法の特徴や短所については、複雑な話となるため本節では説明しません。 詳しくは http://www.linuxfromscratch.org/hints/downloads/files/more_control_and_pkg_man.txt に示されているヒントを参照してください。
LFS システムの利点の一つとして、どのファイルもディスク上のどこに位置していても構わないことです。
他のコンピュータに対してビルドした LFS の複製を作ろうとするなら、それが同等のアーキテクチャであれば容易に実現できます。 つまり
tar コマンドを使って LFS
のルートディレクトリを含むパーティション (LFS の基本的なビルドの場合、非圧縮で 250MB 程度)
をまとめ、これをネットワーク転送か、あるいは CD-ROM を通じて新しいシステムにコピーし、伸張 (解凍) するだけです。
この場合でも、設定ファイルはいくらか変更することが必要です。 変更が必要となる設定ファイルは以下のとおりです。
/etc/hosts
、 /etc/fstab
、 /etc/passwd
、 /etc/group
、 /etc/shadow
、 /etc/ld.so.conf
、 /etc/scsi_id.config
、 /etc/sysconfig/network
、 /etc/sysconfig/network-devices/ifconfig.eth0/ipv4
新しいシステムのハードウェアと元のカーネルに差異があるかもしれないため、カーネルを再ビルドする必要があるでしょう。
最後に新システムを起動可能とするために 8.4. 「GRUB を用いたブートプロセスの設定」 を設定する必要があります。