FreeBSD: portsnap “metadata is corrupt.” トラブル解決!

約一ヶ月間悩んでいた、「あるときから突然 FreeBSD 9.3 で portsnap を実行すると metadata is corrupt. で /usr/ports の更新を完了できない」というトラブルがようやく解決しました。

# portsnap fetch
Looking up portsnap.FreeBSD.org mirrors... 7 mirrors found.
Fetching snapshot tag from ec2-ap-northeast-1.portsnap.freebsd.org... done.
Fetching snapshot metadata... done.
Updating from Sat Sep  3 09:10:09 JST 2016 to Sat Sep 10 11:51:52 JST 2016.
Fetching 5 metadata patches. done.
Applying metadata patches... done.
Fetching 5 metadata files... /usr/sbin/portsnap: cannot open 2cc0c22af8635de9427a30535bf238fc0f7d5d1d634230d208ec3edb9a7b8a80.gz: No such file or directory
metadata is corrupt.

結論としては、man コマンドが正常動作しなくなった理由と同じく、システムがクラッシュした影響を受けていたようです。

portsnap コマンドを使用すると、portsnap fetch を実行した時点で “metadata is corrupt.” となる場合があります。portsnap はデフォルトでは /var/db/portsnap にワークファイルを保存して ports を管理していますが、エラーの意味としては、このディレクトリ下のファイルに破損があるということを意味しているようです。

過去に私が管理しているマシンで発生した時は、/var/db/portsnap と /usr/ports を新しくしたら直りました。
今回も同じだろうと、/usr/db/portsnap と /usr/ports を一度削除して構築し治してみたのですが、結果に変化無し。
検索エンジンで検索してみると、/usr/db/portsnap を初期化しても解決しないというレポートが何件か見つかりました。この場合は、/etc/portsnap.conf にある OSバージョンと一致しないINDEXをコメントアウトすることが解決策になると書かれていました。

# List of INDEX files to build and the DESCRIBE file to use for each
#INDEX INDEX-7 DESCRIBE.7
#INDEX INDEX-8 DESCRIBE.8
INDEX INDEX-9 DESCRIBE.9
#INDEX INDEX-10 DESCRIBE.10

やってみましたが、症状に変化無し。

portsnap fetch はエラーで終わりますが、portsnap update は、ダウンロード出来た範囲の ports 更新をインストールすることが出来ますので、手間ではありますが毎回手作業で更新すれば ports をメンテナンスすることは出来ます。それに ports はパッケージのオプションを変更したい場合に活用するので、気にはなるものの、バイナリーメンテナンスはできるので、しばらく我慢することが出来ていました。

portsnap サーバーに実際にファイルが欠けているんじゃないの?と当初は思ったものの、これだけ長い期間コマンドが失敗して、portsnap サーバー管理者が気づかないわけ無い。自分のサーバーに問題があるはず・・・と、先週から、再度いろいろ試しています。

今回の症状で気づいたことは、

cannot open 2cc0c22af8635de9427a30535bf238fc0f7d5d1d634230d208ec3edb9a7b8a80.gz: No such file or directory

という .gz ファイル名が毎回変わること。
「06b16e3b46d0ffdaee42fe80df8fcd811a17d6e8aeb7aa5447303b64342d10be.gz: No such file or directory」だったり、「30aeacb152126162a90796d60256d77164394b67860af25bf6342da7dc7ae2b6.gz: No such file or directory」だったり。

また、正常なサーバーの /var/db/portsnap は、

# ll /var/db/portsnap/
total 4600
-rw-r--r--  1 root  wheel  2272309  9月 10 12:38 INDEX
drwxr-xr-x  2 root  wheel  2314752  9月 10 12:41 files/
-rw-r--r--  1 root  wheel      451  9月  3 11:58 pub.ssl
-rw-r--r--  1 root  wheel      272  9月 10 12:36 serverlist
-rw-r--r--  1 root  wheel      272  9月 10 12:36 serverlist_full
-rw-r--r--  1 root  wheel       45  9月 10 12:36 serverlist_tried
-rw-r--r--  1 root  wheel      758  9月 10 12:36 tINDEX
-rw-r--r--  1 root  wheel       85  9月 10 12:36 tag

というディレクトリ構成ですが、エラーが出るサーバーは以下のように

total 4552
-rw-r--r--  1 root  wheel  2270119  9月  3 12:00 INDEX
-rw-r--r--  1 root  wheel      325  9月 10 03:30 filelist
drwxr-xr-x  2 root  wheel  2249216  9月  3 09:24 files
-rw-r--r--  1 root  wheel      650  9月 10 03:30 patchlist
-rw-r--r--  1 root  wheel      451  9月  3 11:58 pub.ssl
-rw-r--r--  1 root  wheel      272  9月 10 03:30 serverlist
-rw-r--r--  1 root  wheel      272  9月 10 03:30 serverlist_full
-rw-r--r--  1 root  wheel       45  9月 10 03:30 serverlist_tried
-rw-r--r--  1 root  wheel      758  9月  3 11:58 tINDEX
-rw-r--r--  1 root  wheel      758  9月 10 03:30 tINDEX.new
-rw-r--r--  1 root  wheel       85  9月  3 11:58 tag
-rw-r--r--  1 root  wheel       85  9月 10 03:30 tag.new

となり、ファイル数が違います。ちなみに、No such file となるファイル名は、filelist に記述されていると判明。

ここまで症状を特定できたものの、その後は進展無しで堂々巡り。

昨日、お風呂に入っている時ひらめきました。そうだ、デバッグオプションだ!
お風呂から出た後、FreeBSDサーバーに接続し、「man portsnap」としてみると・・・・・

NAME
     portsnap — fetch and extract compressed snapshots of the ports tree

SYNOPSIS
     portsnap [-I] [-d workdir] [-f conffile] [-k KEY] [-l descfile]
              [-p portsdir] [-s server] command ... [path]

DESCRIPTION
     The portsnap tool is used to fetch and update compressed snapshots of the
     FreeBSD ports tree, and extract and update an uncompressed ports tree.

     In a normal update operation, portsnap will routinely restore modified
     files to their unmodified state and delete unrecognized local files.
     This behavior is different to cvs(1) and cvsup(1).

OPTIONS
     The following options are supported:

     -d workdir   Store working files (e.g. downloaded updates) in workdir.
                  (default: /var/db/portsnap, or as given in the configuration
                  file.)

     -f conffile  Read the configuration from conffile.  (default:
                  /etc/portsnap.conf)

     -I           For the update command, update INDEX files, but not the rest
                  of the ports tree.

     -k KEY       Expect a public key with given SHA256 hash.  (default: read
                  value from configuration file.)

     -l descfile  Merge the specified local describes file into the INDEX
                  files being built.  The descfile should be generated by run‐

って、デバッグオプション、無いじゃない・・・・ガックリ。

続けて、バイナリーかスクリプトなのかをチェックしてみることに。

# which portsnap
/usr/sbin/portsnap
# file /usr/sbin/portsnap 
/usr/sbin/portsnap: POSIX shell script, ASCII text executable

幸いシェルスクリプトでした。中を見てみると、

# $FreeBSD: releng/9.3/usr.sbin/portsnap/portsnap/portsnap.sh 265753 2014-05-09 08:07:05Z delphij $

#### Usage function -- called from command-line handling code.

# Usage instructions.  Options not listed:
# --debug       -- don't filter output from utilities
# --no-stats    -- don't show progress statistics while fetching files
usage() {
        cat <

デバッグオプション あるじゃない!マニュアルに出てこないだけでした。

早速使ってみたところ・・・・

# portsnap --debug fetch
Looking up portsnap.FreeBSD.org mirrors... 7 mirrors found.
Fetching snapshot tag from ec2-ap-northeast-1.portsnap.freebsd.org... 
latest.ssl                                    100% of  256  B   71 kBps 00m00s
done.
Fetching snapshot metadata... 
67ee43e4798e8b7dc9a25eb3e233a7b8ed7d21a35889c0100% of  758  B  206 kBps 00m00s
done.
Updating from Sat Sep  3 09:10:09 JST 2016 to Sat Sep 10 12:02:42 JST 2016.
Fetching 5 metadata patches...
/usr/libexec/phttpget ec2-ap-northeast-1.portsnap.freebsd.org tp/ce32d0a6d457444b39208a3850b475b26f5ac0164a969d5031a3935b88a8b166-2cc0c22af8635de9427a30535bf238fc0f7d5d1d634230d208ec3edb9a7b8a80.gz tp/d1637210e8da68fd2ee844f078bf72519add9068dba84c3a1ec5f786f74d73fa-3c5ddcb4c01b05a39fe127db36a7f1408d522a2890237b482293aa8750cb243a.gz tp/d1637210e8da68fd2ee844f078bf72519add9068dba84c3a1ec5f786f74d73fa-3c5ddcb4c01b05a39fe127db36a7f1408d522a2890237b482293aa8750cb243a.gz tp/4edda449f631dc2deddaa5c49af6c4de90d84593a3288ddaee618e93893aa6dc-fdbd7eefbd47edd77664a09b42fdf7d2d1b17db2411ceb58b6d9a6299772510f.gz tp/5869e2b59a225336cf106d8951633d3bc5e9ad4423a48e411e45c7691305ef9a-e7c6df6deeadac159933b740b2ab185c88beb130fd3679675c3812e502c4298c.gz
xargs: /usr/libexec/phttpget: No such file or directory
 done.
Applying metadata patches... done.
Fetching 5 metadata files... 
/usr/libexec/phttpget ec2-ap-northeast-1.portsnap.freebsd.org f/2cc0c22af8635de9427a30535bf238fc0f7d5d1d634230d208ec3edb9a7b8a80.gz f/3c5ddcb4c01b05a39fe127db36a7f1408d522a2890237b482293aa8750cb243a.gz f/3c5ddcb4c01b05a39fe127db36a7f1408d522a2890237b482293aa8750cb243a.gz f/fdbd7eefbd47edd77664a09b42fdf7d2d1b17db2411ceb58b6d9a6299772510f.gz f/e7c6df6deeadac159933b740b2ab185c88beb130fd3679675c3812e502c4298c.gz
xargs: /usr/libexec/phttpget: No such file or directory
/usr/sbin/portsnap: cannot open 2cc0c22af8635de9427a30535bf238fc0f7d5d1d634230d208ec3edb9a7b8a80.gz: No such file or directory
metadata is corrupt.

/usr/libexec/phttpget コマンドがエラーを出しているのか〜。では、phttpget コマンドのデバッグオプションを試そうと、phttpget の man を取ろうとしたら、man がない!

# man phttpget
No manual entry for phttpget

では、phttpget コマンドの –help オプションを使おうと、「/usr/libexec/phttpget –help」 とすると、phttpget コマンド自体がない!
おいおい。関連コマンドの消失がエラーの原因だったのかよ〜〜〜。ガックリ。コマンドがないのだったらそうとわかるエラーを出して欲しいものです。

確かに、portsnap で問題ないサーバーでは、

# ll /usr/libexec/phttpget 
-r-xr-xr-x  1 root  wheel  14716  8月 27  2015 /usr/libexec/phttpget

と、コマンドが存在しています。原因がわかれば後は簡単。幸い、/usr/src は存在しているので、

# whereis phttpget
phttpget: /usr/src/usr.sbin/portsnap/phttpget
# cd /usr/src/usr.sbin/portsnap/phttpget
# make install
install -s -o root -g wheel -m 555 phttpget /usr/libexec/phttpget

これで、やっと portsnap が復活しました。

# portsnap fetch
Looking up portsnap.FreeBSD.org mirrors... 7 mirrors found.
Fetching snapshot tag from ec2-ap-northeast-1.portsnap.freebsd.org... done.
Fetching snapshot metadata... done.
Updating from Sat Sep  3 09:10:09 JST 2016 to Sat Sep 10 12:02:42 JST 2016.
Fetching 5 metadata patches... done.
Applying metadata patches... done.
Fetching 0 metadata files... done.
Fetching 733 patches.....10....20....30....40....50....60....70....80....90....100....110....120....130....140....150....160....170....180....190....200....210....220....230....240....250....260....270....280....290....300....310....320....330....340....350....360....370....380....390....400....410....420....430....440....450....460....470....480....490....500....510....520....530....540....550....560....570....580....590....600....610....620....630....640....650....660....670....680....690....700....710....720....730. done.
Applying patches... done.
Fetching 27 new ports or files... done.

1ヶ月前に、OS がクラッシュした時に、/usr 上のファイルが何個か吹っ飛んだのですが、いろいろコマンドやファイルが無くなってしまっているようです。

なんにしても、portsnap fetch がエラーで機能しないという問題は解決しました。困った時はお風呂の中でゆっくり考えるのが私には一番!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です