2009年7月アーカイブ

AnyEventとかCoroあたりを知るために、RemedieのMacのbinary版を入れてみたりしているのですが、1つ気になった点がありました。

RemedieはBonjourをサポートしているので、起動すると自動でSafariのブックマークのBojourメニューに現れます。

remedie-bonjour.jpg

ただ、ここからアクセスすることは出来ませんでした。
Bonjourに登録されたアドレスは、

http://kazeburomp.local.:10010/

Safariからでは接続ができなかったようです。

そこでtelnetを用いて、接続をできるか、確認すると、

% telnet kazeburomp.local. 10010
Trying fe80::21c:42ff:fe00:0...
telnet: connect to address fe80::21c:42ff:fe00:0: Connection refused
Trying fe80::21c:42ff:fe00:0...
telnet: connect to address fe80::21c:42ff:fe00:0: Connection refused
Trying fe80::214:51ff:feed:706b...

ここで止まってしまい、connectできません。
よく見ると、アドレスに見慣れない文字、そうIPv6になってます。
どうやらBonjourに登録されたアドレスは、SafariではIPv6として解決されるようです

MacのIPv6といえば、
高木浩光@自宅の日記 - MacユーザはIPv6を切るかnet.inet6.ip6.use_tempaddr=1の設定を
なんていう話もあるので、あまり有効にしていないかもしれません。
自分も無効にしていたはずなんですが、Parallelsの仮想NICが残ってました。試しにこの仮想NICのIPv6をすべて無効にしたところ、SafariのBonjourメニューから普通にRemedieの画面にアクセスができました。

高木先生の指摘点はありますが、IPv6が有効な状態でBonjourにアクセスできないか調べていたのですが、最も良さげなのはRemedieをIPv6のアドレスでListenさせることではないかと思います。

デフォルトの状態では、IPv4でListenするので、netstatでみると

% netstat -nat|grep 10010
tcp4       0      0  *.10010                *.*                    LISTEN

こんな感じ。tcp4と表示されています。

では、RemedieをIPv6化するにはどうしたらいいかと言うことなのですが、幸いなことに、最新版のRemedieはHTTP::Engine::Interfaceを経由してAnyEventを利用しているので、簡単に対応可能です。

AnyEvent::Socketにその説明がありました。
AnyEvent::Socket - useful IPv4 and IPv6 stuff.
AnyEvent::SocketはIPv6対応がすでにされていて、どうやら、tcp_serverのhostに「::」を渡せばいいようです。

Remedieのサーバを起動するコマンドremedie-server.plのオプションでhostを渡せるのですが、その方法がよくわからなかったので、とりあえず、Remedie::CLI::Serverを直接書き換えました。

% vim /Applications/Remedie\ Server.app/Contents/Resources/lib/Remedie/CLI/Server.pm

この50行目あたりのhostのデフォルトを

-     default     => '0',
+    default     => '::',

と書き換えますします。変更後はRemedie Serverを一度再起動です。

さて、もう一度、netstatで確認すると、

% netstat -nat|grep 10010
tcp46      0      0  *.10010                *.*                    LISTEN

となり、IPv6でListenしているのが確認できます。tcp6ではなく、tcp46なのはすみません勉強不足でよくわかりません。IPv4でも接続ができるモードのようです。

telnetでも確認します

% telnet kazeburomp.local. 10010
Trying fe80::21c:42ff:fe00:0...
Connected to kazeburomp.local.
Escape character is '^]'.

今度は何事もなく、接続できました。
SafariのBonjourメニューからも接続ができました。

remedie-menu.jpg

いやいや、Bonjourアツい。 HTTP::Engine + AnyEventで何か作りたい!

暑くなってきたせいか、VMware ESXiを乗っけている自宅サーバが非常に煩いので、調べていたら、電力管理(IntelのSpeedStepとか、AMDのPowerNowの機能)が有効になっていなかったので、してみた。

ちなみに、ネット上にあまり情報はなく、
VMware Communities: How to set Power.CpuPolicy to “dynamic”?
vSphere リソース管理ガイド
ぐらいでした。 (下のは読むべきだったか)

まず、現在の設定の情報を調べます。

vmware-esxi-power-tab.jpg

「構成」のタブを開いて、プロセッサを選択します。 電力管理が有効でない場合は、staticと表示されているはずです。

上記のドキュメントによると、

■static
デフォルトです。VMkernel はホスト上で使用可能な電力管理機能を検出しますが、パワー キャッピング イベントまたは熱イベントで BIOS から要求されないかぎり、その機能を積極的には使用しません。

■dynamic
VMkernel はパフォーマンスに影響を及ぼさずに電力効率を向上させるために、各 CPU の周波数を需要に合わせて最適化します。CPU の需要が増加すると、このポリシー設 定では CPU 周波数も増加します。

とのことなので、電力管理を有効にするためにdynamicに変更を行います。 変更は、「構成」タブの一番左下の、詳細設定を開いて、「Power」を選択

vmware-esxi-power-details.jpg

「Power,CpuPlolicy」のところを、dynamicと書き換えます。
ドキュメントによると、変更後に再起動は必要ないとのことです。

明日からちょっと涼しいみたいだし、本来の目的のファンの音が静かになるかはよくわからない。ただ、VMwareのフォーラムによると、電力消費量が減ることはあるみたい。

VMware ESXi を使っている方は一度確認した方がいいかもですね。

Apacheのmod_headersは、リクエストやレスポンスのヘッダを操作できる便利モジュールなのです。 例えば、レスポンスにとあるヘッダを追加するのあれば、

Header set X-Powered-By OreOre

とHeader setを追加します。
逆に、削除するのであれば、

Header unset X-Powered-By

とします。簡単です。

しかし、上記のHeader set設定だけでは、HTTPのレスポンスコードが200 OKの場合にのみ、Headerが追加されて、500系、400系のエラー、またはRedirectなどの300系のレスポンスの場合には有効にはなりません。

200以外の場合でもHeaderの追加を行なう場合には alwaysオプションを追加します

Header always set X-Powered-By OreOre

これで、Redirectなどの場合でもHeaderが付いてブラウザへレスポンスすることができます。

ところが、unsetの場合は逆にalwaysを付けると、200 OKの場合にだけ有効になり、300、400、500系のHTTPステータスでは、Headerが削除されずにブラウザへ流れうことがあります。
どういうことでしょう。

これには、Apacheの持つheaders_outと、err_headers_outという2つの構造体が関わっています。レスポンスにHeaderを加える際は、この2つの構造体に追加することになります。err_headers_outは文字通り、エラー時のHeaderとして出力されます。エラーではない時にはheaders_outとerr_headers_outがマージされて出力されます。
少し難しいですが、ここで言うエラー時というのはApacheの内部の状態であり、レスポンスのステータスコードではないということです。

mod_perlのHandlerで試してみましょう

■SamleHandler.pm

package SampleHandler;
use Apache2::Const -compile => qw(OK HTTP_NOT_FOUND);
use Apache2::RequestRec  ();

sub handler : method {
    my ($class, $r) = @_;
    $r->headers_out->add('X-Powered-Always','OreOre');
    $r->headers_out->add('X-Powered-Onsuccess','OreOre');
    $r->status(404);
    $r->content_type('text/plain');
    $r->print( "not found" );
    return Apache2::Const::OK;
}
1;

■httpd.conf

Header always unset X-Powered-Always
Header unset X-Powered-Onsuccess
<Location /sample>
  SetHandler perl-script
  PerlResponseHandler SampleHandler
</Location>

SampleHandlerは404を返すだけのHandlerです。
しかし、Handlerの戻り値はOKであり、Apache内部的にはエラーと扱いません。この場合、どのようなレスポンスがブラウザに返るのでしょう。curlを使って確認します。

$ curl -v http://localhost:8080/sample
> GET sample HTTP/1.1
> User-Agent: curl/7.18.2 (x86_64-redhat-linux-gnu) libcurl/7.18.2 NSS/3.12.0.3 zlib/1.2.3 libidn/0.6.14 libssh2/0.18
> Host: localhost:8080
> Accept: */*
> 
< HTTP/1.1 404 Not Found
< Date: Thu, 16 Jul 2009 08:11:52 GMT
< Server: Apache
< X-Powered-Always: OreOre
< Transfer-Encoding: chunked
< Content-Type: text/plain
< 
not found

alwaysオプションを付加してないX-Powered-Onsuccessは消えましたが、X-Powered-Alwaysは削除されませんでした。

これはなぜかというと、mod_headersの実装において、alwaysオプションを付けた時にはerr_headers_outの操作のみを行なうからです。
alwaysというと、エラーでもそうでなくても有効になりそうですが、このようにどの、headers_out構造体に対して効き目があるのか、考えてみる必要があります。Apacheのドキュメントにも書いてありました。

オプションの condition は onsuccess か always のどちらかを指定できます。これは内部ヘッダテーブルのどれを 操作するかを決定します。onsuccess は 2xx ステータスコードの、always は全てのステータスコード (2xx を含む) の意味になります。 あるモジュールでセットされるヘッダをアンセットしたい場合は特に、 どのテーブルが影響を受けるかを実際に試したほうがよいでしょう。

実際、これが問題となるのは、mod_perlのHandlerだけではありません。大規模なWebアプリケーションには必ず用いられるReverseProxyでも同じことが起きます。
このような環境で、Headers unsetを行なっている場合は、Apacheの設定を一度見直してみるのがいいかもしれません。

なんかいろいろ悩んでしまったけど、この方法が一番変更が少ないと思う.

テンプレートの「HTMLヘッダー」に以下を追加

 <script type="text/javascript" src="https://s.hatena.ne.jp/js/HatenaStar.js"></script>
 <script type="text/javascript">
    Hatena.Star.EntryLoader.headerTagAndClassName = [['h2','entry-title'],['h1','entry-title']];
    Hatena.Star.Token = 'token文字列';
 </script>

「ブログ記事」テンプレートの記事タイトルにAタグを追加。

  <h1 id="page-title" class="asset-name entry-title"><a href="<$mt:EntryPermalink$>"><$mt:EntryTitle$></a></h1>

あとは再構築で、完了です。

新しいMTだと、indexやアーカイブのページだとタイトルがh2で、記事のページだとh1という構成になっている。そのため、headerTagAndClassNameを複数個必要。SiteConfigやmtのtagで工夫すればできたのかもしけれないけど。
headerTagAndClassNameに複数個書けるのはドキュメントには無いっぽくて、ソースを見て確認しますた。
この方法だと何よりも変更が少ないのが良いです

自宅サーバを入れ替えました。
ついでに、このblogのMovableTypeも、3.2からMTOS(MT4)へ変更です。
なぜ、アップデートじゃなくて、「変更」なのかというと、 今までフィルタを自分で書いていたので、アップデートするにはフィルタも対応させないといけないということもあっていろいろ面倒なので、前までのデータは引きつかずに新規にMTをいれ、新しいディレクトリにブログを作成しました。

以前までの記事へのリンクは、MTのWEBページ作成機能をつかって作ったページにまとめてあります。

さて、新規MTをいれたことで、今までの記事のリンクが切れてしまいそうですが、それをApacheのAliasを駆使して以前と同じpermanent linkで参照できるようにしています。 今回設定したのは、こんな感じ

Redirect permanent /index.rdf http://feeds.feedburner.jp/nomadscafejp
Redirect permanent /index.xml http://feeds.feedburner.jp/nomadscafejp
Redirect permanent /atom.xml http://feeds.feedburner.jp/nomadscafejp
AliasMatch ^/(banner_grad\.jpg|entry_header_grad\.jpg|mt-site\.js|nav-commenters\.gif|styles-site\.css)$ /path/to/old/blog/$1
Alias /old_index.html /path/to/old/blog/index.html
Alias /archives /path/to/old/blog/archives

feedについては、前からfeedburnerを利用していたので、引き続きRedirectの設定をいれてあります。画像やarchivesディレクトリはそのままの名前でエイリアスし、index.htmlだけ名前を変えてold_index.htmlとしてエイリアスしています。
これで古い記事についても問題なく参照可能です。
ちなみに、以前のblogのデータについては、サーバ移行前後でもpathが変わらないようにしてあるので、MT3.2も設定そのままでOKになっています。

古い記事のコメント・トラックバックは閉じてしまいましたので、何かコメント等があれば、この記事やメールにてお願いします。
今後ともよろしくお願いします。

しばらくリンク切れ等が発生しますm(_ _)m