FreeBSD: ports から perl 5.12 消滅

FreeBSD 8.3 を使用していますが、ports コレクションから perl 5.12が消えてしまいました。
今までもメンテナンスバージョン扱いだった perl 5.12が完全に消滅し、perl 5.16がデフォルトとして設定されたことによります。

私のシステムは、OSをインストールした時の perl 5.12のまま運用してきたため、今回の出来事はかなり痛い!perl が文字処理に向いた言語というだけなら、プログラムをバージョンアップしておしまいなのですが、OS上のパッケージ管理にC言語と同じくらい密着した言語になっていますので、perl のバージョンを更新するということは、portsコレクションからインストールしたアプリケーションの半分くらいはビルドし直しということになってしまいます。Webサーバーなどのサービスを全て停止させれば12時間程度で再構築できるかもしれませんが、Webサーバーの停止はちょっと無理そう。

それでも perl 5.12系は既に ports からソースが消えてしまっているので、いずれは 5.16系に移行せざるを得ないことはわかっています。5.16系に上げることはやむを得ないのですが、恐らく動かなくなるアプリケーションが出て来るはず。これが一番困ります。恐れているのは以下の二つ。

これらアプリケーションには一切問題ないのに、perl の仕様が変更になる度に動かなくなり、解決に時間を取られます。まるで perl がマイクロソフトのアプリケーションみたい!

perl 5.12 系を残すためにがんばったとしても、いずれ perl 5.12ではビルドできないツールが出てきますから、トラブルが発生することがわかっていても今のうちに上げておく方が得策と判断しました。FreeBSD 8.3 の既にサポート切れの状態ですからね。(FreeBSD 8系は 8.4が最新。8.4は飛ばして、9系に上げることになるでしょう。)

/usr/ports/UPDATING を読んで、perl 更新手順を確認。

  Portupgrade users:
    0) Fix pkgdb.db (for safety):
        pkgdb -Ff

    1) Reinstall new version of Perl (5.16):
        portupgrade -o lang/perl5.16 -f lang/perl5.12

    2) Reinstall everything that depends on Perl:
        portupgrade -fr lang/perl5.16

作業自体はとっても簡単。コマンドを3つ発行するだけ。

perl の更新自体は、4時間程度で終わりましたが、perl を使ってビルドされていた依存関係があるパッケージのビルドは12時間では終わる気配無し。24時間経っても半分程度。結局48時間以上掛かりました。

dropbox-api

さて、ビルドが終了したので、 dropbox-api コマンドを試したところ、早速エラーが発生して動きません。

> dropbox-api
Can't locate LWP/UserAgent.pm in @INC (@INC contains: /usr/local/lib/perl5/5.16/BSDPAN /usr/local/lib/perl5/site_perl/5.16/mach /usr/local/lib/perl5/site_perl/5.16 /usr/local/lib/perl5/5.16/mach /usr/local/lib/perl5/5.16 .) at /usr/local/lib/perl5/site_perl/5.16/WebService/Dropbox.pm line 46.
BEGIN failed--compilation aborted at /usr/local/bin/dropbox-api line 19.

dropbox-api コマンドが WebService/Dropbox.pm を呼んで、それがさらにLWP/UserAgent.pm を呼ぼうとしたところ、/usr/local/lib/perl5/5.16/BSDPAN /usr/local/lib/perl5/site_perl/5.16/mach /usr/local/lib/perl5/site_perl/5.16 /usr/local/lib/perl5/5.16/mach /usr/local/lib/perl5/5.16 . のいずれにもそれがないことが原因のようです。示されたパスをチェックしたところ、確かに存在しません。perl 5.12では動いていたのに、依存関係にあるプログラム全部が再構築された訳じゃないの? 過去に存在したライブラリが消えてしまったのか、元から入っていなくてperl 5.16 を使用するようになったためのエラーなのかは不明ですが、 LWP/UserAgent.pm をインストールすればエラーは消えるだろうということは推測できます。

問題は、UserAgent.pm は何のパッケージをインストールすれば入ってくれるのかがわからないこと。ここら辺がFreeBSD ports システムの不便なところ。幸い別のFreeBSDマシンに perl 5.12から更新していないマシンがあるので、それを使って確認してみました。

> grep "site_perl/5.12/LWP/UserAgent.pm" /var/db/pkg/*/+CONTENTS
/var/db/pkg/p5-libwww-6.05/+CONTENTS:lib/perl5/site_perl/5.12/LWP/UserAgent.pm

p5-libwww だと判明しました。確か入っていたはずなんですが、確認してみるとありません。今度は、p5-libwww はどこにあるか探します。コマンドはあるものの、不便!

/usr/ports> make search key="libwww" | grep "Path:"|grep libwww
Path:    /usr/ports/www/libwww
Path:    /usr/ports/www/p5-libwww

ports/www に存在していることが判明したので、ここで make して install。

そして dropbox-api コマンドを発行してみると、、、、、

/usr/ports> dropbox-api find
LWP will support https URLs if the LWP::Protocol::https module
is installed.

まだ、動かないじゃないか!今度は LWP::Protocol::https を探す羽目に。

/usr/ports> make search key="LWP-Protocol-https" | grep "Path:" | grep LWP
Path:    /usr/ports/www/p5-LWP-Protocol-https
Path:    /usr/ports/www/p5-LWPx-ParanoidAgent

/usr/ports/www/p5-LWP-Protocol-https の下でビルドして、LWP::Protocol::https を入れました。さすがにこれで動くだろうと思ったものの、症状に変化無し!

試行錯誤した結果、p5-LWP-Protocol-https の依存関係を調べてみることにしました。

pkg_info -r p5-LWP-Protocol-https-6.04
Information for p5-LWP-Protocol-https-6.04:

Depends on:
Dependency: openssl-1.0.1_9
Dependency: p5-Net-SSLeay-1.58
Dependency: perl5-5.16.3_7
Dependency: p5-Mozilla-CA-20130114
Dependency: p5-IO-Socket-SSL-1.967
Dependency: p5-Net-HTTP-6.06

そういえば、perl 5.12と依存関係があったp5モジュールの中に再構築されていないものがあったことを思い出しました。

/usr/local/lib/perl5/site_perl> ls -lR 5.12|more
total 10
drwxr-xr-x  2 root  wheel   512  8月 13  2013 App
drwxr-xr-x  2 root  wheel   512  2月 17 00:18 auto
drwxr-xr-x  4 root  wheel  5632  2月 18 15:32 mach

5.12/App:
total 0

5.12/auto:
total 0

5.12/mach:
total 4
drwxr-xr-x  3 root  wheel   512  2月 17 01:40 Net
drwxr-xr-x  4 root  wheel  1024  2月 18 15:40 auto

5.12/mach/Net:
total 372
drwxr-xr-x  2 root  wheel     512  2月 16 01:55 SSLeay
-r--r--r--  1 root  wheel   50791  1月 15 08:27 SSLeay.pm
-r--r--r--  1 root  wheel  298373  1月  9 11:27 SSLeay.pod

p5-Net-SSLeay が 5.16用にビルドされていないことが原因かも。

/usr/ports/security/p5-Net-SSLeay に移動して、「make deinstall install clean」と手動で再インストール。

これでようやくdropbox-api コマンドが復活しました。

jdresolve / p5-Net-DNS

次に、jdresolve コマンドをテストしてみたところ、予想通り p5-Net-DNS が 0.68から0.74に更新されてしまい、動かなくなりました。

<テストファイル>

116.58.172.107 - - [01/Nov/2012:00:00:04 +0900]
116.58.172.107 - - [01/Nov/2012:00:00:09 +0900]
66.249.73.3 - - [01/Nov/2012:00:00:10 +0900]
173.199.115.171 - - [01/Nov/2012:00:00:17 +0900]
173.199.116.179 - - [01/Nov/2012:00:10:47 +0900]

<変換結果>

> jdresolve /tmp/ip.txt
Net::DNS::DomainName1035=HASH(0x28496028) - - [01/Nov/2012:00:00:04 +0900]
Net::DNS::DomainName1035=HASH(0x28496028) - - [01/Nov/2012:00:00:09 +0900]
Net::DNS::DomainName1035=HASH(0x28496e24) - - [01/Nov/2012:00:00:10 +0900]
Net::DNS::DomainName1035=HASH(0x289c2f8c) - - [01/Nov/2012:00:00:17 +0900]
Net::DNS::DomainName1035=HASH(0x2849799c) - - [01/Nov/2012:00:10:47 +0900]

こっちの方も重傷。

dns/p5-Net-DNS は更新しないようにしているのですが、今回のようなケースでは避けようがありません。そのために、0.68 のソースを保持していて、今回もバージョン0.68のものからリカバーする予定でした。/usr/ports/dns/p5-Net-DNS を0.68 のものに戻して、再構築しようとしたところ、エラーが発生。

# pwd
/usr/ports/dns/p5-Net-DNS
# make
"Makefile", line 56: Malformed conditional (${PERL_LEVEL} < 501000)
"Makefile", line 58: if-less endif
make: fatal errors encountered -- cannot continue

Makefile 自体がエラーとなってしまい、ビルドすることが出来ません。

.if ${PERL_LEVEL} < 501000 
RUN_DEPENDS+=  p5-Digest-SHA>=5.47:${PORTSDIR}/security/p5-Digest-SHA
.endif

なぜこんな if 文がエラーになるのか?  if 文は PERL_LEVEL とあるので perl のバージョン確認でしょう。501000 は、5.01 か 5.10 を表している気がします。今回は5.16なので、このif文の中は通らないはず・・・・ということで、Makefile の中をコメントアウトしてみました。

#.if ${PERL_LEVEL} < 501000 
#RUN_DEPENDS+=  p5-Digest-SHA>=5.47:${PORTSDIR}/security/p5-Digest-SHA
#.endif

これで、makeをかけたところ、おっ、ビルドが進む!

しかし、今度はMakefileを開けないというエラーに。

===>  Found saved configuration for p5-Net-DNS-0.68
===> Fetching all distfiles required by p5-Net-DNS-0.68 for building
===>  Extracting for p5-Net-DNS-0.68
=> SHA256 Checksum OK for Net-DNS-0.68.tar.gz.
===>  Patching for p5-Net-DNS-0.68
===>  Configuring for p5-Net-DNS-0.68
===>  Building for p5-Net-DNS-0.68
make: cannot open Makefile.
===> Compilation failed unexpectedly.

Makefile は今編集したので存在しています。
が、どうもworkディレクトリの下のものを指しているようです。確かに存在しません。
まったく、次から次へと・・・・

# ls -l work/Net-DNS-0.68/
total 110
-rw-r--r--  1 root  wheel  60002  1月 30  2012 Changes
-rw-r--r--  1 root  wheel   1768  1月 28  2012 DNS.xs
-rw-r--r--  1 root  wheel   2279  1月 27  2012 MANIFEST
-rw-r--r--  1 root  wheel    677  1月 30  2012 META.yml
-rw-r--r--  1 root  wheel   8703  1月 28  2012 Makefile.PL
-rw-r--r--  1 root  wheel  11345  1月 28  2012 README
-rw-r--r--  1 root  wheel   3302  1月 28  2012 TODO
drwxr-xr-x  2 root  wheel    512  1月 30  2012 contrib
drwxr-xr-x  2 root  wheel    512  1月 30  2012 demo
drwxr-xr-x  3 root  wheel    512  1月 30  2012 lib
-rw-r--r--  1 root  wheel   5776  1月 28  2012 netdns.c
-rw-r--r--  1 root  wheel    688  1月 28  2012 netdns.h
drwxr-xr-x  2 root  wheel   1024  1月 30  2012 t

ヒントがないかと、/usr/ports/Mk/bsd.port.mk を開いてMakefileに関する記述をチェックしてみたところ見つかりました。Makefile と Makefile.PL の優先順位に関する記述です。このディレクトリにはMakefile.PLはあるもののMakefileがありません。

# CONFIGURE_SCRIPT
#                               - Name of configure script, relative to ${CONFIGURE_WRKSRC}.
#                                 Default: "Makefile.PL" if USES=perl5 and USE_PERL5=configure
#                                 are set, "configure" otherwise.

Makefile.PLを使うようにするには、環境変数を設定する必要があるようです。

USES=perl5
USE_PERL5=configure

これを設定してmake を掛けてみたところ、なんとビルドに成功。「make deinstall reinstall clean」でp5-Net-DNS 0.68が復活しました!!!

テストファイルをリゾルブしてみたところ、以下のように復活。

> jdresolve /tmp/ip.txt 
tokyo.lifewithunix.jp - - [01/Nov/2012:00:00:04 +0900]
tokyo.lifewithunix.jp - - [01/Nov/2012:00:00:09 +0900]
crawl-66-249-73-3.googlebot.com - - [01/Nov/2012:00:00:10 +0900]
vpn11.radyocetin.com - - [01/Nov/2012:00:00:17 +0900]
173.199.116.179.choopa.com - - [01/Nov/2012:00:10:47 +0900]
     Total Lines: 5
     Total Time : 00:00:01 (5.00 lines/s)
     Total Hosts: 4
  Resolved Hosts: 4 (100.00%)
Unresolved Hosts: 0 (0.00%)
Average DNS time: 0.2500s per request
    Max DNS time: 1s (consider this value for your timeout)

毎度のことですが、perl のバージョンアップとディレクトリ構成、jdresolve と p5-Net-DNS の関係には悩まされます。ちなみに計画を立てて作業を開始したのが、土曜日深夜。ここまでたどり着いたのが火曜日深夜。丸々3日(ビルドが2日半、dropbox-apiとjdresolve の復活に12時間くらい)かかりました。

もう、やりたくない。

<2014/02/21 追記>

このサーバーでの perl 5.12→5.16への更新が終了したため、リモートにある別の FreeBSD 8.3 サーバーの perl も 5.16 に更新することにしました。

  • CPU: Celeron 466
  • Memory: 256MB

この「システム管理メモ」サーバー(Celeron 600MHz/256MB)よりも CPU速度が約75%でメモリ容量が半分。ただしCPU稼働率は非常に低いものです。どのくらいビルド時間が掛かるのかと思っていましたが、perlとその依存関係があるパッケージ全てを再構築したのに10時間程度であっけなく終了。しかも、dropbox-api コマンドの動作に問題なく、手動でperlモジュールをインストールし直す必要もありませんでした。インストールされているパッケージ数が多少少ないという面はあったのですが、それでも40時間近く差を付けられてしまいました。メモサーバーで動いている、radiko のエンコーダーとか、WordPress が相当重いのでしょうが、更新時間だけを評価するなら、別マシンを再構築してコンテンツだけ移行した方が早い気がします。でもまあ、サーバー停止時間を殆どゼロで更新作業するにはやむを得ないのかもしれません。
結果がわかっていたなら、クローニングした別マシンでビルドして、パッケージ化したバイナリーをインストールするという手もあったかも。

コメントを残す