先週あたりから FreeBSD の Ports メンテナンスで pkg_version や portversion コマンドを使うと大量のエラーが出力され、メンテナンスすべきパッケージが何か話からなという問題が発生するようになりました。
ports のメンテナンスは、
- portsnap fetch
- portsnap update
を実行し、最後に
- portversion -vL=
で、更新が必要なパッケージを表示させますが、portversion コマンドが以下のようにエラーを吐くようになってしまいました。
Unknown modifier 't' Unknown modifier 't' Unknown modifier 't' Unknown modifier 't' Unknown modifier 't' "/usr/ports/Mk/bsd.sites.mk", line 957: Malformed conditional (!empty(_PERL_CPAN_ID) && ${_PERL_CPAN_FLAG:tl} == "cpan") Unknown modifier 't' "Mk/bsd.port.mk", line 2929: Unclosed conditional/for loop "Mk/bsd.port.mk", line 2929: Unexpected end of file in for loop. "Mk/bsd.port.mk", line 6708: Unclosed conditional/for loop "Mk/bsd.port.mk", line 6708: Unexpected end of file in for loop. 1 open conditional: at line 1179 (evaluated to true) make: fatal errors encountered -- cannot continue /usr/local/lib/ruby/site_ruby/1.9/pkgtools/portsdb.rb:237:in `join': can't convert nil into String (TypeError) from /usr/local/lib/ruby/site_ruby/1.9/pkgtools/portsdb.rb:237:in `index_file' from /usr/local/lib/ruby/site_ruby/1.9/pkgtools/portsdb.rb:247:in `db_dir=' from /usr/local/lib/ruby/site_ruby/1.9/pkgtools/portsdb.rb:167:in `setup' from /usr/local/lib/ruby/site_ruby/1.9/pkgtools/pkgtools.rb:242:in `init_pkgtools_global' from /usr/local/sbin/portversion:191:in `block in main' from /usr/local/lib/ruby/1.9/optparse.rb:882:in `initialize' from /usr/local/sbin/portversion:84:in `new' from /usr/local/sbin/portversion:84:in `main' from /usr/local/sbin/portversion:383:in `'
ports サーバー上のファイル自体が壊れて、このような症状になることは過去に時々あったのであまり気にしていなかったのですが、1週間経っても症状に変化がないことから、調査を開始しました。
ちなみに、今回のエラーは FreeBSD 8.3 で発生しています。
FreeBSD host_name 8.3-RELEASE-p16 FreeBSD 8.3-RELEASE-p16 #0:
エラーメッセージを検索してみたところ、同様の症状がFreeBSD関係の掲示板に投稿されていましたが、 8.3 はサポート終了しているので、8.4 に上げろとか、freebsd-update コマンドで、OSを最新パッチバージョンにしろとか役に立たないメッセージばかり見つかりました。Windowsのサポートじゃあるまいし、なんてレベルの低いアドバイスかと感じます。こういうアホなアドバイスしか書き込めない奴は、一度公開サーバーのシステム運用をやってみるべきでしょう。サービス運用中のサーバーは、ports のエラーメッセージくらいでOSを更新できるわけ無いじゃない!それぞれ、それなりの事情があって、特定のバージョンを使っているわけですからね。サーバーが離れた場所にあって、万が一リブートに失敗すると数日システムが停止するようなケースもあるわけですから、最終的にはOSの更新を行うとしても、その前にコマンドがエラーを出力する原因が何かがわからなければ、バージョンアップが解決方法だとしても、OSを更新する気にはなりません。
まずは、上記エラーと同様のメッセージを出力する操作が何かを確認してみたところ、
- portversion
- pkg_version
- /usr/ports 以下での make
の動作に問題がありそうだと判明しました。portversion は rubyスクリプト、pkg_version はバイナリプログラムですが、どちらも make を実行しているだけで、エラー自体は make が Makefile を実行する時に出力しているようです。怪しいのは /usr/ports/Mk ディレクトリ以下のファイルでしょう。
ports コレクションの更新を2月頃を最後にしばらく行っていなかったサーバーから、ports 以下をコピーして、最新 ports と置き換えてみたところ、(当然ですが)エラーは発生しません。
ports の Makefile の動作は、
- ターゲットディレクトリの Makefile が読み込まれる。
- 1のMakefile から、ports/Mk/bsd.port.pre.mk が読み込まれる。
- ports/Mk/bsd.port.pre.mk から ports/Mk/bsd.port.mk が読み込まれる。
- port/Mk/bsd.port.mk から複数の .mk ファイルが読み込まれる。
ということで、複雑すぎてファイルの中身全部を確認することは Mkディレクトリの製作者でもなければちょっと無理。しかし、必要なファイルは Mk ディレクトリ以下だけでクローズしていると思われるため、旧 ports/Mk ディレクトリ以下だけを最新 ports の下のものと置き換えたら解決しそうなものです。
やってみたところ、コマンド自体は実行されるようになりましたが、tar.mk が見つからないというエラーになります。
# portversion -vL= "/usr/ports/Mk/bsd.port.mk", line 1524: Could not find /usr/ports/Mk/Uses/tar.mk make: fatal errors encountered -- cannot continue dbus-glib-0.100.2 < needs updating (port has 0.100.2_1) ffmpeg-0.7.15_1,1 < needs updating (port has 2.1.1_3,1) gettext-0.18.3.1 < needs updating (port has 0.18.3.1_1) jpeg-8_4 < needs updating (port has 8_5) libltdl-2.4.2_2 < needs updating (port has 2.4.2_3) libtool-2.4.2_2 < needs updating (port has 2.4.2_3) p5-Params-Validate-1.08 < needs updating (port has 1.09) pcre-8.34 < needs updating (port has 8.34_1) phpMyAdmin-4.1.14 < needs updating (port has 4.2.0) rpm-3.0.6_16 < needs updating (port has 3.0.6_17) rtmpdump-2.4_1 < needs updating (port has 2.4.20130923_2) tiff-4.0.3_1 < needs updating (port has 4.0.3_2) xf86-video-radeonhd-1.3.0_5 < needs updating (port has 6.14.6_3)
旧 Mk/Uses には tar.mk が含まれていないため、新Mk/Users/tar.mk を旧Mkにコピーして実行したところ、portversion コマンドに関してはエラーが出なくなりましたが、portupgrade や make を実行すると “unknown modifier” が表示される現象は発生し続けてしまいます。
何か環境変数を設定すれば、回避できるのではないかと期待していたのですが、ヒントにつながるメッセージさえ見つからない感じです。
ここまでの結論としては、/usr/ports/Mk 以下の .mk ファイル内の記述に何か問題がありそう というものです。
やむを得ないので、FreeBSD 8系の最新 8.4 ではどうなのかを試すことにしました。8.4 のマシンがないので、仮想マシンを使う事にしました。幸い、仮想WordPress 用 Virtual Box に FreeBSD 8.4 がありますので、これを使ってテストしてみることにしました。
FreeBSD vwp1 8.4-RELEASE FreeBSD 8.4-RELEASE #0 r251259
設定してから時間が経過しているため更新すべきパッケージは多かったものの、FreeBSD 8.4 のports 更新ではエラー無し。
root@vwp1:~ # portsnap fetch && portsnap update && portversion -vL= Looking up portsnap.FreeBSD.org mirrors... none found. Fetching snapshot tag from portsnap.FreeBSD.org... done. Fetching snapshot metadata... done. Updating from Fri May 9 20:10:46 JST 2014 to Fri May 9 21:23:25 JST 2014. Fetching 4 metadata patches... done. Applying metadata patches... done. Fetching 0 metadata files... done. Fetching 4 patches... done. Applying patches... done. Fetching 0 new ports or files... done. Removing old files and directories... done. Extracting new files: /usr/ports/japanese/edict-fpw/ /usr/ports/japanese/epwutil/ /usr/ports/math/octave/ /usr/ports/www/chromium/ Building new INDEX files... done. [Updating the portsdb <format:bdb_btree> in /usr/ports ... - 24357 port entries found .........1000.........2000.........3000.........4000.........5000.........6000.........7000.........8000.........9000.........10000.........11000.........12000.........13000.........14000.........15000.........16000.........17000.........18000.........19000.........20000.........21000.........22000.........23000.........24000... ..... done] apache24-2.4.6 < needs updating (port has 2.4.9_2) apr-1.4.8.1.5.2 < needs updating (port has 1.5.1.1.5.3) autoconf-wrapper-20130530 < needs updating (port has 20131203) automake-wrapper-20130530 < needs updating (port has 20131203) bash-4.2.45 < needs updating (port has 4.3.11_2) bind99-9.9.4 < needs updating (port has 9.9.5_12) cclient-2007f,1 < needs updating (port has 2007f_1,1) cmake-2.8.12.1 < needs updating (port has 2.8.12.1_4) cmake-modules-2.8.12.1 < needs updating (port has 2.8.12.1_1) cups-client-1.5.4_1 < needs updating (port has 1.7.2) cups-image-1.5.4_1 < needs updating (port has 1.7.2) docbook-1.4_1 < needs updating (port has 1.5) docbook-4.1_4 < needs updating (port has 4.5_1) (=> 'textproc/docbook-sgml') docbook-4.2 < needs updating (port has 4.5_1) (=> 'textproc/docbook-sgml') docbook-4.3 < needs updating (port has 4.5_1) (=> 'textproc/docbook-sgml') docbook-4.4_2 < needs updating (port has 4.5_1) (=> 'textproc/docbook-sgml') docbook-4.5_2 > succeeds port (port has 4.5_1) (=> 'textproc/docbook-sgml') docbook-5.0_1 < needs updating (port has 5.0_2) (=> 'textproc/docbook-xml') docbook-sk-4.1.2_4 < needs updating (port has 5.0_2) (=> 'textproc/docbook-xml') docbook-xml-4.2_1 < needs updating (port has 5.0_2) docbook-xml-4.3 < needs updating (port has 5.0_2) (=> 'textproc/docbook-xml') docbook-xml-4.4_1 < needs updating (port has 5.0_2) (=> 'textproc/docbook-xml') docbook-xml-4.5 < needs updating (port has 5.0_2) (=> 'textproc/docbook-xml') docbook-xsl-1.76.1_1 < needs updating (port has 1.76.1_2) docproj-2.0_1 < needs updating (port has 2.0_2) fontconfig-2.10.95,1 < needs updating (port has 2.11.0_2,1) freetype2-2.5.0.1 < needs updating (port has 2.5.3_2) gdbm-1.10 < needs updating (port has 1.11) gettext-0.18.3.1 < needs updating (port has 0.18.3.1_1) ghostscript9-9.06_4 < needs updating (port has 9.06_6) help2man-1.43.3 < needs updating (port has 1.43.3_1) igor-1.376 < needs updating (port has 1.431) ja-freebsd-doc-43088_1,1 < needs updating (port has 44393,1) ja-jvim-3.0.j2.1b < needs updating (port has 3.0.j2.1b_1) jasper-1.900.1_12 < needs updating (port has 1.900.1_14) java-zoneinfo-2013.h < needs updating (port has 2014.b) jpeg-8_4 < needs updating (port has 8_5) lcms2-2.5 < needs updating (port has 2.6_1) libICE-1.0.8,1 < needs updating (port has 1.0.8_2,1) libSM-1.2.2,1 < needs updating (port has 1.2.2_2,1) libX11-1.6.2,1 < needs updating (port has 1.6.2_2,1) libXau-1.0.8 < needs updating (port has 1.0.8_2) libXaw-1.0.12,2 < needs updating (port has 1.0.12_2,2) libXdmcp-1.1.1 < needs updating (port has 1.1.1_2) libXext-1.3.2,1 < needs updating (port has 1.3.2_2,1) libXmu-1.1.2,1 < needs updating (port has 1.1.2_2,1) libXp-1.0.2,1 < needs updating (port has 1.0.2_2,1) libXpm-3.5.11 < needs updating (port has 3.5.11_2) libXt-1.1.4,1 < needs updating (port has 1.1.4_2,1) libcheck-0.9.11 < needs updating (port has 0.9.12) libffi-3.0.13 < needs updating (port has 3.0.13_1) libfontenc-1.1.2 < needs updating (port has 1.1.2_2) libgcrypt-1.5.3 < needs updating (port has 1.5.3_2) libgd-2.1.0_1,1 < needs updating (port has 2.1.0_3,1) libgpg-error-1.12 < needs updating (port has 1.13) libiconv-1.14_1 < needs updating (port has 1.14_3) libltdl-2.4.2_2 < needs updating (port has 2.4.2_3) libtool-2.4.2_2 < needs updating (port has 2.4.2_3) libxcb-1.9.1 < needs updating (port has 1.10_2) libxml2-2.8.0_2 < needs updating (port has 2.8.0_5) libxslt-1.1.28_1 < needs updating (port has 1.1.28_3) libyaml-0.1.4_2 < needs updating (port has 0.1.6) m4-1.4.17,1 < needs updating (port has 1.4.17_1,1) mkfontscale-1.1.1 < needs updating (port has 1.1.1_1) mutt-1.5.22 < needs updating (port has 1.5.23_1) mysql55-client-5.5.34 < needs updating (port has 5.5.37) mysql55-server-5.5.34 < needs updating (port has 5.5.37) netpbm-10.35.89 < needs updating (port has 10.35.89_1) openssl-1.0.1_8 < needs updating (port has 1.0.1_12) pcre-8.33 < needs updating (port has 8.34_1) pecl-pdflib-2.1.10 < needs updating (port has 3.0.4) perl5.14-5.14.4_3 < needs updating (port has 5.14.4_6) php5-5.4.21 < needs updating (port has 5.4.28) php5-bz2-5.4.21 < needs updating (port has 5.4.28) php5-ctype-5.4.21 < needs updating (port has 5.4.28) php5-dom-5.4.21 < needs updating (port has 5.4.28) php5-exif-5.4.21 < needs updating (port has 5.4.28) 以下省略
更新されているパッケージ、例えばPHP や Perl が古いままのため問題が発生していない可能性もあるので、リストされているパッケージを更新した後に、再度 portversion と make をテストしてみましたが、やはりエラーは出ず。
make のバージョンを比較して見ると、
<8.3>
# ll /usr/bin/make -r-xr-xr-x 1 root wheel 381312 4月 10 2012 /usr/bin/make
<8.4>
# ll /usr/bin/make -r-xr-xr-x 1 root wheel 383984 Jun 3 2013 /usr/bin/make*
となっているので、ひょっとすると make コマンドの仕様が少し異なっているのかも と思うものの、make コマンドの仕様を比較する方法がわかりません。(わかったとしてもあまり意味があるとも思えないし。)
原因は /usr/ports/Mk 以下ファイルの記述が、FreeBSD 8.3 の make と一致していない事は間違いないようです。Mkディレクトリの構造を理解してもう少し探せば回避策は見つかるかもしれませんが、8.4 に更新するのとどちらが早いか、簡単か? 仮に、回避方法が見つかったとしても、portsnap で自動更新される Mk 以下の内容をエラーが発生たびに毎回手作業でメンテナンスするの?
8.4では問題は発生しないことが確認できているため、 8.4 にバージョンアップするのが最も短時間で解決出来る方法と考えざるを得ないようです。
サーバーが離れた場所にあるので出来る事ならOSの更新作業はリモートで行いたくないところなんですが、やらなくちゃいけないのかも。