2009-12-05

Google Public DNS を早速、試してみた

購読している RSS フィードのひとつで、Google が DNS サービスを提供し始めたことを知った。とりあえず、試してみることにした。大まかな流れはこんな感じ(↓):

  1. AirMac ユーティリティによる Time Capsule の設定
  2. Snow Leopard Server: DNS の設定
  3. Snow Leopard (クライアント版) 側の設定
  4. 稼動確認
  5. ローカルの DNS を落としても、名前解決できるか

AirMac ユーティリティによる Time Capsule の設定

うちは Time Capsule をインターネットへのルータとして使っている。 部屋で使っている Mac たちは DNS の設定を DHCP 経由で、この Time Capsule に訊きにいく。 個別に設定することもできるが、今回は、この大元を変更してみることにした。

Time Capsule に限らず一般的なルータはとくに設定しなければ、DNS の設定を ISP の DHCP サーバから引っぱってくる。ISP から契約の際に送られてくる書類一式にも DNS サーバの IP アドレスは書かれているはずだが、それを手作業で設定したのは遠い昔の話だ。Time Capsule でこれを独自の設定に変更するには「AirMac ユーティリティ.app」を使う。

「AirMac ユーティリティ.app」を起動したら、ツールバーから「インターネット」を選び。さらにメインビューの「インターネット接続」タブを選ぶ。中段に「DNS サーバ」の IP アドレスを入力するフィールドが 2 つ用意されている。デフォルトだと、ここには ISP から取得した DNS サーバの IP アドレスが 2 つ表示されている(グレー表示になっている)。これを上書きすれば良い。

うちの LAN では Snow Leopard Server でもローカルな DNS を稼動させて、LAN 上の機器の名前解決を担当させている。2 つある DNS サーバのうち最初の方は、ローカルな Snow Leopard Server の IP アドレスを入力してある。今回の Google Public DNS の IP アドレス (8.8.8.8) は、もう一方の方に入力した。

入力後、右下の「アップデート」ボタンを押せば、Time Capsule が再起動する。

Snow Leopard Server: DNS の設定

mini で稼動させている DNS サーバはローカルな LAN 上の機器の名前(とアドレス)しか解決できない。他のリクエストは上位の(外部の) DNS サーバにリクエストを転送することで解決を図るようになっている。そのためには転送する相手のアドレスを設定する必要がある。

「サーバ管理.app」を起動し、サイドバーからサーバを選び、さらに「DNS」を選ぶ。メインビューのツールバーで「設定」を選ぶと「フォワーダ IP アドレス」のリストがある。これまで、ここには ISP 提供の DNS サーバのアドレスを 2 つ入力してあったが、それを消して、Google Public DNS の 2 つのアドレス (8.8.8.8 と 8.8.4.4) を追加した。右下の「保存」を押せば完了。

Snow Leopard 側の設定

DHCP で接続情報を取得するようになっていれば(これがデフォルト)、とくに設定する必要はない。あえてすることと言えば、「システム環境設定」を開いて DNS の設定を確認するぐらい。

mini が停止する可能性もあるから、クライアント版はローカル DNS だけにクエリーを飛ばすようにはしていない。Time Capsule の設定にしたがって、ローカル DNS と Gogole Public DNS の 2 つのアドレスが使われるようになっている (実は、3 つ目として ISP 提供の DNS のアドレスも飛んできていた; これは Time Capusle が気をきかせたのかな)。

ちなみに、Snow Leopard の場合、DNS の設定は /etc/resolv.conf にも書かれている。設定を確認するだけなら、こいつを cat するのがてっとり早いかも。ただし、このファイルは自動生成されるもののようで (/etc にあるのはシンボリックリンク、実体は /var/run/resolv.conf)、これを書き換える必要はない。というか、書き換えてはダメ。中にはこんな風なことが書かれているから。

(/etc/resonv.conf のコメント)
# Mac OS X Notice
#
# This file is not used by the host name and address resolution
# or the DNS query routing mechanisms used by most processes on
# this Mac OS X system.
#
# This file is automatically generated.

稼動確認

まあ、普通に web をうろついてみたけど、問題ない。 dig を叩いて、有名どころのアドレスを調べてみたり。

ローカルの DNS を落としても、名前解決できるか

これは稼動確認のオマケ。ローカル DNS が Google Public DNS にフォワードするように設定したのだから、通常 LAN 内での DNS リクエストは一旦、ローカル DNS に届く。ただし、mini が停止する可能性も考慮してクライアント (MacBook) では、第2候補に Google Public DNS を明示的に指定している。この設定が期待どおりに効果を発揮するなら、mini 上のローカル DNS を停止しても、MacBook は問題なく web ページを開いたりといった作業ができるはず。それを確認してみる。

手順は、mini で「サーバ管理.app」から DNS サービスを停止させ、MacBook で web を見るだけ。

やってみた。問題ない。

関連リンク

2009-12-04

twitter より (2009-12-03)

  • Google 日本語入力(β) か(→ http://bit.ly/821f3M。ケータイやiPhoneといった入力に制約の強い機器では良いと思う。 posted at 11:56:40
  • くそ、URL がおかしなことになった。正しくはこちら → http://bit.ly/6E05d0 posted at 11:57:26
  • けどねえ。予測変換っていうのはキー入力を減らすためには良いんだけど、それがそのまま入力スピードのアップにつながるかっていうと、疑問が残る。 posted at 11:58:46
  • たまに入力する人なら大いに助けになると思う。でも、毎日、それなりの分量を入力する人はかえって足手まといにならないか? > 予測変換 posted at 12:00:19
  • こう打ったら、こう変換される、っていうのを身体が覚えちゃうと思うんだ。ヒトの身体(っていうか脳だけど)の方でかかる最適化の邪魔をしちゃう気がするんだよ posted at 12:01:24
  • カナ漢のように「指にすいつく」ようにして使いたいモノって、あまり賢さを演出する必要はないと思う。むしろ、愚直であった方が良い。SKK でなければ書けない体になっているからかな。余計なことはしなくて良い。ただ変換してくれ。 posted at 12:04:17
  • 他の漢字圏の人たちって、どう思っているのかね (・ω・)? posted at 12:05:16
  • そうか〜、iMac には外部ディスプレイもつなげられるのか。30インチをつなげて同時の表示できる。ふーん、たしかに Mac Pro、かたなしだねえ。 posted at 12:51:34
  • ピカピカ液晶は嫌いなんだけどなあ。MacBook は買うと同時にノングレアのフィルムを買っておいて、すぐに貼った。 posted at 12:53:30
  • 27 とかじゃなく、30 インチで出してくれれば良かったんだよ。なら、たぶん飛びついていたよ。 posted at 12:55:01
  • ディスプレイという一番かさばる筐体に本体を一体化してしまうっていう発想は、確かに画期的だったよな。今じゃ珍しくなくなったけど。 posted at 12:57:34
  • CRT だった「おむすび」世代、その次が液晶になった「大福」、そして液晶と体型。筐体の進化で見ると 3 世代目なのか > iMac posted at 13:03:25

2バイトエンティティじゃなくて、文字参照の変換

「す」のような文字列を見たことがあるだろうか? これまで、なんとなく「2バイトエンティティ」と呼んでいたんだけど、正しくは「文字参照」、それも「数値文字参照」と言うようだ。今回、これが混じったテキストから「文字参照」だけを一致する文字に変換する必要に迫られた。ブラウザに表示させれば元の文字列に戻るから(「す」は「す」)、テキストが少量なら手作業で変換したと思う。が、ちょっとサイズが大きかったのだ(4MBほど)。仕方がないのでプログラムを書いて対応することにした。

仕様の確認

まずは、仕様を見てみようとW3C を訪れた。該当する部分をちょこっと抜粋する。

(W3C: HTML 4.01 Specification: 5.3 Character References より) Character references are a character encoding-independent mechanism for entering any character from the document character set.

「文字参照 (character references)」 は、「数値文字参照 (numeric character references)」と「文字実体参照 (character entity references)」に分かれる、ともある。この数値文字参照の数値の部分は ISO 10646 の文字番号だということ。

ISO 10646 は符号化文字集合の国際規格のひとつ。誤解を恐れず、ものすごくおおざっぱに言うと Unicode と同じもの。正確なことは Wikipedia を始めとする資料にあたること。(→ 関連リンクを参照せよ)

Ruby で変換

CGI.unescapeHTML を使うと一発のようだけど、こいつは「数値文字参照」以外も変換してしまう。やりたいことは「数値文字参照」だけを文字に変換すること。もう少し手間をかける必要がある。どうせなら CGI.unescapeHTML を使わずにやってみよう。

「〹」の "12345" の部分が文字番号なのだから、文字列中から「&#?????;」(?は数字) というパターンを取り出して頭2文字と尾1文字を削れば良い。パターンを取り出すときは、正規表現を使えばコードは簡潔になるはず。

問題は ISO 10646 の文字番号から文字(列)を生成することだが、Ruby 1.9 ではこれが拍子抜けするほど簡単にできる。書式変換関数(C の printf/sprintf に相当)を使うだけだ。

プログラム全体はフィルタにする。標準入力から読んで加工して標準出力に書き出す。それを入力が終わるまでループする。こうなる(↓):

(convert_entity.rb)
 1: pattern = /&#[1-9][0-9]*;/
 2: 
 3: def convert(entity)
 4:   num = entity[2...-1].to_i     # entity must be "〹"
 5:   fs = "%c".encode("UTF-8")
 6:   fs % num
 7: end
 8: 
 9: STDIN.each { |line|
10:   while pattern === line
11:     entity = Regexp.last_match[0]
12:     line[entity] = convert(entity)
13:   end
14:   STDOUT.puts line
15: }

5 行目で、書式変換のテンプレート (fs) に対して encode("UTF-8") を呼び出しているのは、この文字列のエンコードを UTF-8 にするため。これがないと fs は US-ASCII になってしまい、書式変換関数の呼び出して例外が出てしまう。この他にソースファイルの先頭に「# coding: utf-8」という行を追加する方法もある。

肝になるのは前述の書式変換関数による文字番号から文字(列)への変換(convertメソッド)、および 12 行目の元の行に対する置換。正規表現とマッチした文字列をそのまま部分文字列置換の引数としている。

Ruby では Apple orange Grape という文字列(これを s とする)に対して、s["orange"] = "Peach" を実行すれば s = "Apple Peach Grape" となる。

この、「パターンマッチ」→「マッチした部分を対応する文字(列)」で置き換え → マッチに戻る、というサイクルを繰返すことで元の文字列中の数値文字参照が順次、置き換わっていく。長い行に文字参照がいくつもある場合は効率が悪いんだけど、その分、記述がすっきりしたものになった。

実行結果はこんな風(↓)。例によって長い行は "\" のところで折り返してある。

[mini:~] mnbi% cat .data.txt 
<p>&#12377;&#12409;&#12390;&#12398;&#22987;&#12414;&#12426; \
&#12539;&#12539;&#12539;&#12363;&#12394;(&#12539;&#969;&#12539;) \
&#65311;</p>
[mini:~] mnbi% cat data.txt | ruby1.9 convert_entity.rb
<p>すべての始まり・・・かな(・ω・)?</p>

ちなみに、上記のコードは Ruby 1.9 専用。これは String.encode を使っているからだが、そもそも文字列の扱いが 1.8 までと 1.9 とでは異なため、肝心の 6 行目が動かない。1.8 でやるなら CGI.unescapeHTML を使うことになる。また、インタープリタに -Ku を渡さないとダメ。

さて、これで一応、期待どおりに動くプログラムができた。あと気になるのは文字番号から文字(列)への変換の部分。これですべての文字を変換できるのだろうか? それとも、ある領域の番号は変換に失敗したりするのだろうか? この問いに答えるには、ISO 10646 や Unicode、そして UTF-8 のことをもっと調査する必要がある。それは別の機会に回そう。今日のところは(だいたい)動いていることで良しとする。

PHP で書くと・・・

ちょっと、たどたどしいんだが、Ruby で書く前に PHP でもちゃちゃっと書いてみた。それがこれ(↓):

(convert_entity.php)
 1: <?php
 2: $pattern = '/&#[1-9][0-9]*;/';
 3: 
 4: while (!feof(STDIN)) {
 5:   $raw = fgets(STDIN);
 6: 
 7:   $coocked = "";
 8:   $head = 0;
 9:   $tail = strlen($raw);
10:   $pos = 0;
11: 
12:   while ($head < $tail) {
13:     $count = preg_match($pattern, $raw, $matches,
14:                         PREG_OFFSET_CAPTURE, $head);
15:     if ($count > 0) {
16:       $entity = $matches[0][0];
17:       $pos = $matches[0][1];
18:       if ($head < $pos) {
19:         $normal = substr($raw, $head, $pos - $head);
20:         $coocked = $coocked . $normal;
21:       }
22:       $coocked = $coocked . 
23:                  html_entity_decode($entity, ENT_NOQUOTES, 'UTF-8');
24:       $head = $pos + strlen($entity);
25:     } else {
26:       $coocked = $coocked . substr($raw, $head);
27:       break;
28:     }
29:   }
30: 
31:   fwrite(STDOUT, $coocked);
32: }
33: ?>

これも先の Ruby のプログラムと同様、フィルタになっている。Ruby 版の方がぐっと短くなっているのは、わたしが Ruby の方を少し余計に知っているせいかも。PHP でも Ruby 版と同様の書き方にできるかもしれない。ただ、こちらの方が少し効率は良いはず。変換が進むにつれ探す部分が短くなるから。

関連リンク

2009-12-03

Ruby 1.9.1 を ports でインストール

実行結果だけを示す。要した時間は約5分。

[mini:~] mnbi% sudo port install ruby19
--->  Computing dependencies for ruby19
--->  Fetching ruby19
[... snip ...]
--->  Building ruby19
--->  Staging ruby19 into destroot
--->  Installing ruby19 @1.9.1-p243_0
--->  Activating ruby19 @1.9.1-p243_0
--->  Cleaning ruby19
[mini:~] mnbi% rehash
[mini:~] mnbi% ruby1.9 -v
ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-darwin10]

PHP: date.timezone に関する警告問題

ちょっと必要があって、Snow Leopard Server 上で WordPress を動かすことにした。その過程で出くわしたことを書き留めておく。全体の流れはこんな風(↓):

  1. PHP モジュールを有効にする
  2. date.timezone に関する警告
  3. phpinfo() を実行する
  4. クライアント版では・・・

PHP モジュールを有効にする

Snow Leopard Server の Web サービスは Apache が使われているが(バージョンは 2.2; in 10.6.2)、デフォルトでは PHP モジュールが無効になっている。まずは、これを有効にすることが必要。

手順は簡単で、「サーバ管理」を起動し Web の「設定」から php5_module のチェックを入れるだけ。あとはウィンドウ右下にある「保存」ボタンを押せば完了。

手作業でやったとしても、/etc/apache2 あたりの httpd.conf を書き換えるだけなんだが、GUI があるとカンタンではある。Apache の停止や再起動も意識せずに済むし。何より、Snow Leopard Server では GUI 中心の管理作業が前提になっているから、不用意に手作業を混じえない方が良い。ちなみに、Apache の管理を手作業でやる前は /etc/apache2/ReadMe.txt を読むべし。httpd.conf の運用に関する注意点が書かれている。

phpinfo() を実行する

まずは、PHP モジュールが動作していることを確認するため、phpinfo() を表示させてみる。これには、通常こういうファイルを用意する(↓)。

(phpinfo.php)
 1: <?php
 2: phpinfo();
 3: ?>

たいした手間ではないけど、Snow Leopard Server ならこれが省略できる。あらかじめ /Library/WebServer/Documentsinfo.php というファイルが用意されているからだ。内容は上とほとんど同じ。違いはコメントで注意書きがある程度。ただし、肝心な phpinfo() を呼び出す行がコメントアウトされている。注意書きによれば、これを実行することでサーバの設定情報が見えるからだと言う。

コメントアウトを外してこのファイルを表示させてみる。上記のフォルダは Snow Leopard Server 上の Apache の DocumentRoot なので、ブラウザからこんな URL を開けば良い。

http://mini/info.php

PHP Version 5.3.0 で、2009-07-19 にビルドされたことなんかがわかる。

date.timezone に関する警告

と、ここで、Apache のエラーログをチェックしてみた。すると、こんな警告が出ていた。

PHP Warning: phpinfo(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Asia/Tokyo' for 'JST/9.0/no DST' instead in /Library/WebServer/Documents/info.php on line 5

要は date.timezone を設定しろ、ってこと。ぐぐってみたところ、それには php.ini を使うとわかった。Snow Leopard Server では PHP モジュールを有効にすると、/etc/php.ini が作られる(/etc/php.ini.defaultというファイルがコピーされるだけっぽい)。

該当する部分はこんな感じになっている。見てわかるようにデフォルトの状態では date.timezone は設定されていない。

(/etc/php.ini)
 1:    (...)
 2: [Date]
 3: ; Defines the default timezone used by the date functions
 4: ; http://php.net/date.timezone
 5: ;date.timezone =
 6:    (...)

↑の5行目のコメントアウトを外し、値として Asia/Tokyo を設定すれば良い。警告メッセージは出なくなる。

クライアント版では・・・

比較のために、クライアント版の Snow Leopard でも上記のことを確認してみた。違いは以下のとおり。

  • PHP モジュールを有効にするのは手作業
  • phpinfo() のためのファイルは自分で用意
  • PHP は同じ Version 5.3.0 (ビルド時間も同一)
  • date.timezone に関する警告はやはり出る
  • /etc/php.ini はないので、/etc/php.ini.default を手作業でコピーする
  • 書き換える内容は同じ

その他

ちなみに、Snow Leopard Server には MySQL が同梱されていて、これも「サーバ管理」から有効にするだけで使える。WordPress を動かすのに必要なものは本体以外にないってこと。phpMyAdmin はインストールされていないけれど、WordPress を(ちょっと)動かすだけなら必要性は低い。

関連リンク

2009-11-29

O'Reilly の Ebook を買ってみる

少し前から気になっていた O'Reilly の電子本、Ebook を試しに 1 冊、買ってみることにした。この Ebooks の特徴は、複数のデバイスに最適化されたフォーマットのものが用意されている点。また、一度購入するとすべてのフォーマットを好きなだけダウンロードすることができる。さらに、データファイルには DRM がかかっていないため、機器から機器へのコピーも自由。だからといって、無料で配布して良いわけではない。印刷された本と同じような扱いなら良いよ、ということ。個人で自分ひとりが使う分には、細かいことは気にしなくて良いわけだ。

用意されているフォーマットは 3 種類。PDF、ePub、そして Mobi。簡単に言えば、PDF はパソコン(Mac や PC)用、ePub は iPhone 用(Stanza というアプリを使う)、Mobi は Amazon の Kindle 用だ。

印刷された本は好きだし、メディアとしての紙はとても優秀だと思う。ただ、こいつは物理的な実体を伴う。保持するためには空間コストが高くつく。平たく言えば、本を溜めこむと部屋が狭くなる。世の中には自室で遭難するほど本を溜めこむ強者もいるようだけど、ともあれその空間占有率はデジタル化された情報にくらべればはるかに高い。読んで処分する(売る、捨てる、等)のがまっとうな対処だけど、それが簡単にできるなら溜まったりしない。読んでない本は処分できないし(せっかく手に入れたのに)、読んだ本も「また読みたくなるかも」とか「この情報がいつか必要になるかも」などと思ってこれも処分しづらい。

今ある本をどうにかするための手段として有望なのが、スキャナによるデジタル化だ。バラす手間がかかることが難点だが、PDF にしてしまえば空間占有率は無視できるほど低くなる。一方で、これから入手する本への対処も必要だ。スキャンして減らした分を新しい本で埋めてしまっては元も子もない。そこで、Ebook のような電子書籍を試すことにしたわけだ。

今回、買ってみたのは Programming Interactiveity (O'Reilly のカタログへのリンク; プレビューあり) という本(↓)。2009年7月に出版された比較的新しいものだ。

さて、実際の見た目はというと・・・