FreeBSDのPorts collection運用

FreeBSDにはpkgというパッケージシステムがあるんですが、更新が遅いのとmakeオプションを変えられないので長年Portsで運用してきました。

また、一時期portsのビルドが面倒になってpkg運用一本に切り替えようかともしたのですが、長期運用で少しづつ各パッケージのバージョンを上げていこうとすると、パッケージ間で参照しているライブラリのパッケージバージョンが不一致で、どちらかしかインストールできないなんて状態になったりで結局あきらめました。
※バイナリpkgが導入された直後の昔のことなんで、今は良くなってるんでしょうかね?

そもそもFreeBSDのports/pkgの更新も「portsコード→バイナリパッケージ(pkg)」の順番に更新される訳なんですが、このタイムラグが結構あって、最新のセキュリティパッチとか、ただでさえportsコードに取り込まれるのが遅かったりするので、pkgだと相当遅かったりします。

そんなわけでひたすらPorts運用一筋。教科書?に載ってないようなPorts運用のノウハウをちょっと書いてみたいと思います。

更新作業について

各パッケージは日々バージョンアップされていきます。昨今ではセキュリティ関連の更新が多く「安定稼働しているから」と、古いバージョンのまま放置するわけにもいきません。

そんなわけで定期的に各portsの、アップデート作業を行うのがPorts運用の基本となります。

とりあえず/usr/ports/UPDATEは読みましょう。大規模なアップデートが有る時に、必要な作業が載ってます。読んでないと嵌まることあります。

基本的にportupgradeを使ってます。rubyのいらないportmasterが好まれるようですが、あっちは良く分かりません。

portupgrade -R <port name>

とか、-Rオプションおすすめです。

依存パッケージも更新してくれるのですが、依存パッケージが古くてコンパイル通らないとか良く有るので。

make uninstall or pkg delete/make installとかすると、ちょいちょい大変な目に遭います。と言うのも、新しいPortsのビルドが通らないことが、困ったことに「結構良く」あります。

原因は様々ですが、その原因の一つが、以下に挙げる/usr/local/lib/comat/pkgだったりします。

/usr/local/lib/compat/pkgの管理

昔は共有ライブラリのバージョンを上げたら、ライブラリのI/Fが変わってて、依存しているパッケージが軒並み動作がおかしくなるなんて事がありました。

今では共有ライブラリのパッケージを更新すると、古いバージョンがこのディレクトリに置かれて、そして新しいバージョンがインストールされるようになっています。

それはそれで互換性の面でありがたいのですが、古いライブラリは自動的には消してくれないんですよね。さらに、残った古いライブラリが悪さして、別のパッケージのビルドが通らないなんて事も起こります。

ライブラリのパッケージ自体を削除しても、移動された古いライブラリはそのまま残ってしまうんですが、それが悪さをすることもしばしば…。

なので、定期的にチェックして手動で消す必要があります。

pkg shlib <shard library>

ってすると、その古いライブラリを参照しているパッケージを教えてくれます。依存しているパッケージを再ビルドすると新しいパッケージを参照するようになります。

それらのパッケージを一つずつ、portupgrade -fで再ビルドしましょう。全てのパッケージを再ビルドして、古いライブラリを参照しているパッケージが無くなったら、ようやく消すことが出来ます。

portupgrade -f `pkg shlib -qR <shard library>`

ってやって、一括してアップデートするのも手です。

それでも新しいportsがビルドできない

ports運用上の最大の障害がこれ。クリーンインストールなら問題なくても、長年アップデートを繰り返してきた環境だと、わりと遭遇します。

組み合わせると動かないパッケージがある

よく似た機能のパッケージで、普通はどちらかしか使わないのを両方入れてたら、それらに依存しているパッケージがビルドできないパターンがあります。

netatalkとavahi/mdnsあたりだったかな。

機能のかぶるパッケージが入ってないかチェックしましょう。

依存関係が機能不全

依存パッケージが入ってるのに「無い」って言われてビルドできなかったり、逆に無いのに自動的にインストールされずにビルドエラーで終わってしまうパターン。

ports側で依存関係が変わったりとか、パッケージの構成変更や、ports名の変更とかだったりします。

普通は/usr/ports/UPDATEをよく見てると注意喚起が載ってたりするんですが、載ってないこともあります。

関連するパッケージを一度消してから、再インストールすると上手くいくことが多いです。

それでもどうしてもビルド出来ない

まだ古いパッケージをアンインストールしていないなら、とりあえず待ちましょう。ports側で修正されることがあります。

依存関係を疑って、一度消しちゃった場合は、portsを古いバージョンに戻してビルドします。

そのために、portsはportsnapではなくSubversionで更新するのがおすすめです。該当するportsのディレクトリだけ古いバージョンに戻してビルドします。