2006年1月29日日曜日

portsnapでwgetを使わせる

先日、



(FreeBSD) portsnapが暴走する?



と書いたように、phttpgetが暴走することはなくなりました。しかし、やはり、トラブルはまだ続いています。



どうもその場所のプロキシーサーバの動作が異常で、頻繁に、ファイルのダウンロードに失敗します。



ダウンロードに失敗しても、phttpgetってば、もう一度ダウンロードしようとしてくれません。こんなかんじでした。



  • portsは頻繁に更新されているので、1~2週間ぶりにportsnapを実行したところ、全部で1000個くらいのファイルをダウンロードしようとしました。


  • とうぜん、いくつかのファイルのダウンロードは失敗します。


  • もう一度portsnapを実行すると、すでにダウンロード済みのファイルも、もう一度ダウンロードしてるみたいです。


  • しかも、portsnapを実行すると、どのファイルをダウンロードすべきかを調べる処理をしているらしいんですが、この処理が、VMwareの中で実行するには、けっこう重い処理のようです。


というわけで、何回、何十回とportsnapを実行しても、いつまでたっても、portsnap fetchが成功しないのです。



というわけで、頭にきたので、phttpgetを改造することにしました。



・・・やめました。phttpgetってば、ソフトウェアとして完成度が低いです。



たとえば、データ読み出しのタイムアウト時間が15秒とか決めうち(hard coding)されてるんです。最近の流行で、プロキシーサーバでウイルスチェックとかやってる場合、全部プロキシーサーバまでダウンロードが終わって、ウイルスチェックが終わってから、クライアント(パソコン)へ一挙にデータ転送がはじまります(プロキシなしだと、水道からチョロチョロ水が流れるみたいなかんじになりますが、その余計なプロキシが挟まると、チョロチョロ水をバケツに一度ためて、一杯になってから一度にまく、みたいになる)。そういう場合、15秒でタイムアウトというのは、ちょっと短すぎます。



で、代替案が、ひらめきました。

phttpgetは捨てる。wgetで置き換える!

wgetというのは、HTTPやFTPでファイルをダウンロードするソフトで、昔からあるのでけっこう有名だと思います。/usr/ports/ftp/wgetとしてportsにもなっています。昔から使われているだけあって、ダウンロードに失敗したときの再実行もあるし、タイムアウト時間も自由に調整できます。



で、考えること、3分経過。こんなシェルスクリプトができあがりました。実質的に、重要な処理は最後の1行だけです。



#! /bin/sh



WGET=/usr/local/bin/wget



if [ $# -lt 2 ]
then
    echo "usage: $0 server [file ...]"
    exit 64
fi



SERVER=$1
shift



echo $* | tr ' ' '\n' | ${WGET} --base="http://${SERVER}/" --no-clobber --input-file=-



「phttpget-wget.sh」をダウンロード



phttpgetを置き換える例



  1. cp phttpget-wget.sh /usr/libexec/


  2. mv /usr/libexec/phttpget /usr/libexec/phttpget.org


  3. ln -s /usr/libexec/phttpget-wget.sh /usr/libexec/phttpget


このシェルスクリプトで、/usr/libexec/phttpgetを置き換えたところ、これまで何度やっても失敗していたportsnap fetchが、1発で成功しました。



唯一、phttpgetが優れているのは、HTTPのkeep aliveを使って、1回のコネクションで、複数のファイルをダウンロードしているところでしょうか。wgetもkeep aliveをサポートしているのですが、どうも上記のような用途では、keep aliveを使わないみたいです(リンクをたどって再帰的にダウンロードするときのみkeep aliveかな?)。



keep aliveを使うと、通信のオーバーヘッドが減るので、スループットが向上するのはわかりますが、そもそもphttpgetはそのほかの点で(エラー処理があまいなど)、ファイルをダウンロードするソフトウェアとして、致命的に欠点があります。



というわけで、その「いやがらせプロキシーサーバ」があるネットワーク環境では、phttpgetは捨てました。自宅では、phttpgetは快調に動いているんですけどね。



余談



シェルスクリプトのことを、

シェル

と省略して呼ぶ人がたまにいるんです。これ、すごく気持ち悪いです。省略するんだったら、

スクリプト

って呼ぶべきですよね。シェルと省略するのは、

ジャイアント・パンダを、ジャイアントと省略する

ようなものです。





2 件のコメント:

  1. ヘタレなサーバ管理者2006年9月13日 19:10

    これだ!!!
    余計なお世話のProxyに苦しんでいた私への福音です。
    ついでにfetchも捨てちゃいます。
    余計なお世話のProxyのせいで、portsのダウンロードに毎回失敗して、とまったらwgetしてたおバカな私です・・・
    余計なお世話のProxy通してportupgradeを夜間実行させるのなら、やっぱりwgetですよね・・・

    返信削除
  2. 私も、以前、portupgradeで、wgetを使うようにしていました。そのときは、/etc/make.confで、FETCH_CMDなどを設定しました(詳しくは、/usr/ports/Mk/bsd.port.mkを参照)。
    ・・・ですが、落とし穴がありました。
    /usr/ports/distfiles以下に、中途半端にダウンロードされた、ファイルの断片があったりすると、wgetでダウンロードしなおしたとき、wgetは親切にも、ファイル名を「なんとか.1」、「なんとか.2」のように変えて、上書きしないようにしてくれるのでした。
    というわけで、portupgradeを実行するたびに、ファイルがダウンロードされるだけ・・・
    という、気が付いてみれば、笑いとばせる話なんですが。

    返信削除