6.3. パッケージ管理

パッケージ管理についての説明を LFS ブックに加えて欲しいとの要望をよく頂きます。 パッケージ管理ツールがあれば、インストールされるファイル類を管理し、パッケージの削除やアップグレードを容易に実現できます。 パッケージ管理ツールでは、バイナリファイルやライブラリファイルだけでなく、設定ファイル類のインストールも取り扱います。 パッケージ管理ツールをどうしたら・・・ いえいえ本節は特定のパッケージ管理ツールを説明するわけでなく、その利用を勧めるものでもありません。 もっと広い意味で、管理手法にはどういったものがあり、どのように動作するかを説明します。 あなたにとって最適なパッケージ管理がこの中にあるかもしれません。 あるいはそれらをいくつか組み合わせて実施することになるかもしれません。 本節ではパッケージのアップグレードを行う際に発生する問題についても触れます。

LFS や BLFS において、パッケージ管理ツールについて触れていない理由には以下のものがあります。

ヒントプロジェクト (Hints Project) ページに、パッケージ管理についての情報が示されています。 それらが望むものかどうか確認してみてください。

6.3.1. アップグレードに関する問題

パッケージ管理ツールがあれば、各種ソフトウェアの最新版がリリースされた際に容易にアップグレードができます。 全般に 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 に対してリンクするよう再コンパイルしなければなりません。 古いライブラリに依存しているパッケージすべてを再コンパイルするまでは、そのライブラリを削除するべきではありません。

6.3.2. パッケージ管理手法

以下に一般的なパッケージ管理手法について示します。 パッケージ管理マネージャーを用いる前に、様々な方法を検討し、特にそれぞれの欠点も確認してください。

6.3.2.1. すべては頭の中で

そうです。 これもパッケージ管理のやり方の一つです。 いろいろなパッケージに精通していて、どんなファイルがインストールされるか分かっている人もいます。 そんな人はパッケージ管理ツールを必要としません。 あるいはパッケージが更新された際に、システム全体を再構築しようと考えている人なら、やはりパッケージ管理ツールを必要としません。

6.3.2.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 ディレクトリにインストールした上で、先ほどのシンボリックリンクをこのディレクトリを指し示すように置き換えます。

PATHLD_LIBRARY_PATHMANPATHINFOPATHCPPFLAGS といった環境変数に対しては /usr/pkg/foo ディレクトリを加える必要があるかもしれません。 もっともパッケージによっては、このやり方では管理できないものもあります。

6.3.2.3. シンボリックリンク方式による管理

これは一つ前に示したパッケージ管理テクニックの応用です。 各パッケージは同様にインストールします。 ただし先ほどのようなシンボリックリンクを生成するのではなく /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 ディレクトリにインストールする方が容易なことかもしれません。

6.3.2.4. タイムスタンプによる管理方法

この方法ではパッケージをインストールするにあたって、あるファイルにタイムスタンプが記されます。 インストールの直後に find コマンドを適当なオプション指定により用いることで、インストールされるすべてのファイルのログが生成されます。 これはタイムスタンプファイルの生成の後に行われます。 この方法を用いたパッケージ管理ツールとして install-log があります。

この方法はシンプルである利点がありますが、以下の二つの欠点があります。 インストールの際に、いずれかのファイルのタイムスタンプが現在時刻でなかった場合、そういったファイルはパッケージ管理ツールが正しく制御できません。 またこの方法は一つのパッケージだけが、その時にインストールされることを前提とします。 例えば二つのパッケージが二つの異なる端末から同時にインストールされるような場合は、ログファイルが適切に生成されません。

6.3.2.5. インストールスクリプトの追跡管理

この方法はインストールスクリプトが実行するコマンドを記録するものです。 これには以下の二種類の手法があります。

環境変数 LD_PRELOAD を使えば、インストール前にあらかじめロードされるライブラリを定めることができます。 パッケージのインストール中には cpinstallmv など、さまざまな実行モジュールにそのライブラリをリンクさせ、ファイルシステムを変更するようなシステムコールを監視することで、そのライブラリがパッケージを追跡管理できるようになります。 この方法を実現するためには、動的リンクする実行モジュールはすべて suid ビット、sgid ビットがオフでなければなりません。 事前にライブラリをロードしておくと、インストール中に予期しない副作用が発生するかもしれません。 したがって、ある程度のテスト確認を行って、パッケージ管理ツールが不具合を引き起こさないこと、しかるべきファイルの記録を取っておくことが必要とされます。

二つめの方法は strace を用いるものです。 これはインストールスクリプトの実行中に発生するシステムコールを記録するものです。

6.3.2.6. パッケージのアーカイブを生成する方法

この方法では、シンボリックリンク方式によるパッケージ管理にて説明したのと同じように、パッケージが個別のディレクトリにインストールされます。 インストールされた後には、インストールファイルを使ってアーカイブが生成されます。 このアーカイブはこの後に、ローカル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 を参照してください。

6.3.2.7. ユーザー情報をベースとする管理方法

この手法は LFS に固有のものであり Matthias Benkmann により考案されました。 ヒントプロジェクト (Hints Project) から入手することが出来ます。 考え方としては、各パッケージを個々のユーザーが共有ディレクトリにインストールします。 パッケージに属するファイル類は、ユーザーIDを確認することで容易に特定出来るようになります。 この手法の特徴や短所については、複雑な話となるため本節では説明しません。 詳しくは http://www.linuxfromscratch.org/hints/downloads/files/more_control_and_pkg_man.txt に示されているヒントを参照してください。

6.3.3. 他システムへの LFS の配置

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 を用いたブートプロセスの設定」 を設定する必要があります。