2010/01/24

Kindle で青空文庫や iPhone ドキュメントを読む

Amazon が Kindle で active content を作成するためのKindle Develpment Kitの公開を発表しました。

Amazon 曰く、「実際の天候に即したアクティビティをお薦めする旅行書や、参加人数やアレルギーに応じてお薦めを変える料理本が作れるよ」との事です。これは面白い試みですね。

そんな Kindle の紹介記事を読んでいるうちに、つい 1click 注文で、手元に Kindle Internationalが...。22日深夜に注文したのですが、国際便での送達にも関わらず、届いたのは24日朝でした。予定では26日以降とのことでしたので、非常に迅速な到着です。さすがは Amazon。

いつものように、開封の写真をいくつか。

Amazon の通常配送箱そのままのような外箱で、脇についている帯をピリピリひっぱって箱を開けます。Once uppn a time... の表現が素敵です。




箱を開けるといきなり本体が現れます。画面に表示されている接続手順は、表面フィルムではなく Kindle 自身に書かれています。これは Kindle の利点を明確に知らしめる素晴らしい演出だと思いました。




梱包物はこんな感じで、非常にシンプルです。



本体の大きさは、概ねA5サイズの一般書籍と同様。




なお、Kindle 自身のより詳しい説明などは、PC Watch の紹介記事などが解りやすいです。

Kindle を購入時に考えていた当面の用途は大きく2つ。1つは、青空文庫で公開されている書籍を読むことで、もう1つは、Appleなどが公開している、テクニカルドキュメントを読むことでした。

というわけで、早速試してみました。

青空文庫を手軽に読むには PDF へ変換するのが一番です。今回の変換は、青空キンドルを活用させていただきました。このサイトを Bookmarklet を使って利用することで、青空文庫のコンテンツを、Kindle に適したPDFへ簡単に変換出来ます。公開、どうも有難うございます。

PDF生成後は、Kindle を USB で iMac へ接続し、documents フォルダへ copy します。これだけで、転送したファイルがHOMEメニューに表示され、読み始めることが可能です。

表示してみるとこんな感じになります。



Kindle 自身の性能に、フォントの大きさと美しさがあいまって、大変綺麗に表示され、読み進めることになんの問題もありません。素晴らしいです。

今度は、Apple から公開されている iPhone 用の開発リファレンスファイルを転送してみました。表示してみるとこんな感じになります。



視力検査のような小さな文字のサイズとなってしまい、視力の弱い私には、正直、読み続けるのは厳しいです。PDFであるため、Kindle のウリであるフォントサイズ変更も出来ません。

幸いPDFでも画面の表示方向を切り替えることは可能で、こうすることで、多少表示される文字が大きくなります。



多少ページ送りが煩雑になるのが残念ですが、これならば、私の視力でも読むことができそうです。

無駄に紙へ印刷することなく、また、重い印刷物を持つことなく、通勤中などに各種ドキュメントを読めるのは大変に便利です。しばらく鞄の友として持ち歩いてみようと思います。

MacOS X の sshd の待ち受けポートを変更する方法

MacOS X では、ssh がシステムへ統合されており、Remote Login の手段として簡単に利用出来ます。

手順は、System Preferences の Sharing へ入り、Remote Login のチェックボックスを有効化するだけです。これで ssd が起動さ れます。

通常 ssh は 22番ポートで待ち受けます。今回、それ以外のポートでも待ち受けるできるように設定を変更しようとしたのですが、/etc/sshd_config などを変更してもうまくいきませんでした。

検索してみたところ、Mac OS X Hintsサイトで10.4: Change the default sshd port Networkという解説記事を発見することが出来ました

コメントまで含めてまとめると、次のようになります。

  • sshd の設定は /System/Library/LaunchDaemons/ssh.plist で行う
  • 標準の待受け設定は、Listeners の SockServiceName Key で指定された string 値の ssh。ここへは、/etc/service 内の名称、ポート番号のいずれをも指定できる。
  • 待受ポート番号を追加するには、Sockets 内の Listeners Keyと並列に Alternate Listeners Key で指定する。
  • plist ファイルを変更した場合には、launchctl の load/unload で再読み込みを行う

例えば、ssh を 10000番ポート番号で追加待ち受けするように設定するには、/System/Library/LaunchDaemons/ssh.plist に対し、

        <key>Sockets</key>
        <dict>
                <key>Alternate Listeners</key>
                <dict>
                        <key>SockServiceName</key>
                        <string>10000</string>
                </dict>
                <key>Listeners</key>
                <dict>
                        <key>SockServiceName</key>
                        <string>ssh</string>
                        <key>Bonjour</key>
のような記述を行い、その後、
% sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
% sudo launchctl load /System/Library/LaunchDaemons/ssh.plist
を実行することになります。もし、System Preferences で Remote Login を有効にしていない場合には、チェックボックスを有効化するか、service コマンドで start しましょう。
% sudo service ssh start

貴重な情報を公開してくださった、Mac OS X Hintsサイトへ感謝いたします。

2010/01/20

Firewall で仕切られたネットワークから iChat を Google Talk クライアントに使う

前回のiCal と Google Calender 連携を Firewall で仕切られたネットワークから使う方法に引き続き、Firewall で仕切られたネットワーク内での話です。

iChat は jabber プロトコルの採用により、Google Talk 用のクライアントとして利用できます。ただ、残念ながら Snow Leopard に付属の iChat 5.x は Firewall を超えられないようです。

Apple のサポートページで公開されているiChat:ネットワーク環境設定で HTTP プロキシと HTTPS プロキシの両方が設定されている場合、HTTPS プロキシがデフォルトになるなどを読むと、以前の iChat は、iChat の環境設定で Proxy を利用するかどうかを選択できたようですが、Snow Leopard の iChat には、この選択肢が存在しませんでした。

iCalの場合では、サーバのホスト名解決だけを細工すればその後は Proxy を超えてくれましたが、iChat の場合 packet を読む限り、直接サーバとの接続を試みるようで、この細工は効きません。

幸いにして、Bloody Fingersさんの blog に書かれていた、Google Talk in iChat behind a firewallという記事で、HTTPS Proxy を用いた一般的なトンネリングにより接続出来ることが紹介されていました。

この記事ではトンネリング用のソフトウェアとしてproxytunnelを利用していますが、私は普段、同種のソフトウェアとして stoneを常用しています(公開ありがとうございます)。そこで、以下のような設定で試してみたところ、無事接続できるようになりました。

proxyserver.example.com:8080/http 5223 'CONNECT talk.google.com:5223 HTTP/1.0'

残念ながら私はテキストチャットしか利用しない為、ビデオ機能などが利用できるかどうかは不明です。

iChat が Proxy を超えられるようになるまでは、この環境で対応しようと思います。

2010/01/19

iCal と Google Calender 連携を Firewall で仕切られたネットワークから使う方法

MacOS X 10.5(Leopard) 以上に付属してくる iCal では、CalDAV を通じてGoogle Calendar と同期が行えます。

設定方法は、例えば、Enable Google Calendar in Apple's iCalの他、様々なところで分かりやすく紹介されている通りです。また、Snow Leopard 付属のiCal 4.x では、Google Calendr に関しては、より簡単に設定が行えるように改良されています。

しかし、残念ながら私の環境では、Firewal で区切られたネットワークからは、うまく同期が行えませんでした。HTTP/HTTPS のプロキシを正しく設定した状態でも、
Your calendar couldn't be refreshed.

The Connection to account "Google Calendar" failed
because the network is unreachable.

のようなエラーになってしまいます。



全く同じ設定でありながら、直接 Internet へ接続すれば、問題なく同期させることが可能です。

tcpdump でパケットを眺めていたところ、どうやら iCal は、

  • Accounts の ServerSetting 内の Server address へホスト名が書かれている場合には、そのIP Address を解決するためにネームサーバへ問い合わせに行く。
  • 問い合わせに失敗すると上記のエラーになる。
という実装になっているのでは、と思わせる挙動を確認することができました。

そこで、

  • iCal の設定で、Server address へ www.google.com のIPアドレスを書き込む(または /etc/hosts へ www.google.com のエントリを追加する)
ことで、無事、同期が行われるようになりました。



通信自体は HTTPS Proxy 経由で行えるので、なんとなく Bug のような気がしますが、もし同じ現象で困っている場合には、参考になればと思います。

2010/01/12

.CFUserTextEncoding へは改行コードを付与すべきでない

MacOS X では、現在ユーザの利用しているテキスト言語環境を示す情報が、ホームティレクトリの .CFUserTextEncoding ファイルへ書き込まれます。

実際には、System Preferences の Languages & Text を変更し、再度 login することでシステムにより値が設定されるようで、例えばシステム言語を日本語へ設定した場合には、この値は 1:14 に、同じく英語では0:0、ドイツ語では0:3 などへ設定されます(値の意味に関しては、MacOS X 英語環境で Flash を日本語モードで使うをご参照ください)。

この際、設定値の行末へ改行コードは付与されません。よって、もし何らかの理由でこの値を自分自身で変更する場合にも、行末へ改行コードを付与しないよう、注意すべきです。

今回、私は行末へ改行コードを付与してしまったために、愛用させていただいているCarbon Emacsの言語環境が日本語にならず、はまってしまいました。

.CFUserTextEncoding は、環境変数 __CF_USER_TEXT_ENCODING の生成に使われます。具体的には、.CFUserTextEncodingファイルの値へUID値を付与し __CF_USER_TEXT_ENCODING を生成しているようです。

Carbon Emacs では、この __CF_USER_TEXT_ENCODING 環境変数を参照して稼働環境を切り替えます。具体的には、/Applications/Emacs.app/Contents/Resources/site-lisp/site-start.d/japanese-init.el 内に於いて、

(string-match ":1:14\\'" (getenv "__CF_USER_TEXT_ENCODING"))

の結果を判定し、切り替えています。

ここで string-match の regexp部は \' が指定されているため、文字列またはバッファ終端であることが期待されています。そのため、もし .CFUserTextEncoding ファイルの行末に改行コードが付与されている場合、この判定式に適合しなくなってしまうのです。

今回は Carbon Emacs で問題の生じる事象を発見しましたが、システムの自動生成では改行コードが付与されていない以上、他にも同様の判定方法を行っているソフトウェアも存在するかもしれません。

もし何らかの理由により、自分で設定する場合には、Terminal などから、

 % echo -n 1:14 > ~/.CFUserTextEncoding

のように、-n オプションを指定した echo コマンドを使用する、などの方法が安全だと思いました。

1年以上も前に自身が書いたエントリと同じ内容でハマるというのは、あまりに進歩がないなぁ、と改めてショックを受けた一日でした。

2010/01/07

git リポジトリを HTTP で公開する設定でハマリました

私の関係しているプロジェクトで、空 git リポジトリを作成し、HTTP 経由でアクセス出来るように設定する必要がありました。

git リポジトリ HTTP 経由でアクセスできるように公開する設定方法に関しては、「Setting up a git repository which can be pushed into and pulled from over HTTP(S).が大変参考になります。また、ありがたい事に、このドキュメントは、Yuanyingさんによって日本語訳も公開されています。

既に過去何回か行った案件であり、且つドキュメントが整備されているにも関わらず、情けないことに再びハマってしまったので、いくつかポイントを整理しておこうと思います。

まずサーバ側の設定作業ですが、setup-git-server-over-http.txtに書かれている通り、概要は次のような手順になります。

1. HTTP サーバを用意する
2. 認証を含めた WebDav の設定を行う
3. リポジトリを準備する

「リポジトリを準備する」は、コマンドライン的にはこんな感じです。

% su
# cd /var/www  # HTTPサーバで設定したリポジトリの公開場所
# mkdir sample_rep.git
# cd sample_rep.git
# git init --bare
Initialized empty Git repository in /var/www/sample_rep.git/
# git update-server-info
# chown -R www . # HTTPサーバを動作させる user が www である場合

ポイントは「git update-server-info を実行すること」「パーミッションを正しく設定しておくこと」の2点で、非常にシンプルです。

このリポジトリを pull/push するクライアント側の設定手順は、以下の通りです。ここで、git クライアントは MacOS X 上の 1.6.6 を想定していますが、特に OS 依存の箇所はないかと思います。またサーバとクライアントの間には firewall は存在しないことを仮定しています。
  1. ~/.netrc を適切に設定する
  2. ユーザ名の含まれていない URL を用いて、リポジトリを clone する
  3. ローカルリポジトリへファイルを commit する
  4. リモート側のリポジトリとローカル側の参照を指定して push する
以下、これらの作業に関係して、私がハマってしまった事例とともにを説明します。

1. ~/.netrc を使うのであれば、URL へユーザ名を埋め込んではならない

認証の必要な http URL へ git でアクセスするには2つの指定方法があります。1つは、ユーザ名をURL内へ埋め込む方法で、もう1つは curl経由でのアクセスを利用し curl が参照する .netrc へ認証情報を書いておく方法です。

前者は、例えば、こんな感じになります。

% git clone http://username:password@server.example.com/sample_rep.git

とはいえ、URLへパスワードを直接書いてしまう方法は好ましい方法ではなく、あまり現実には使われないかと思います。

パスワードを埋め込まない指定も可能です。

% git clone http://username@server.example.com/sample_rep.git

この場合、別途パスワードの入力が求められます。

% git clone http://username@server.example.com/sample_rep.git
Initialized empty Git repository in /users/n-miyo/p/sample_rep/.git/
Password: 

この方式の問題は、頻繁にパスワードの入力を求められることです。何度もパスワードを入力することは、危機意識が薄くなるので、あまり好ましいことではありません。

一方、ホームディレクトリへ .netrc というファイルを作成し、その中に認証情報を書いておく、という方式も利用可能です。HTTP アクセスで利用される libcurl がこの情報を参照し、適切に認証情報を送り出してくれます。

.netrc の記述方法に関しては、MacOS X では ftp(1) のマニュアルページに詳しいですが、基本的には、machine 行へ該当ホスト情報、login へユーザ名、password へパスワードを書いておきます。

% cat ~/.netrc
machine server.example.com
login n-miyo
password PASSWORD

このファイルが読まれてしまわないよう、パーミッションを 600 へ設定するなど、十分気を付けましょう。

.netrc を使う方法であれば、URL へユーザ名やパスワードを埋め込む必要はありません。

% git clone http://server.example.com/sample_rep.git
Initialized empty Git repository in /users/n-miyo/p/sample_rep/.git/
% 

さて、~/.netrc が適切に設定されている状態で、前者の様に URL 内へユーザ名を埋め込んだ場合はどうなるのでしょうか。この場合、まずはパスワードの入力が求められることになります。もし、return を空打ちするなどにより、パスワードへ空文字が入力された場合には .netrc の設定が使われることになります(パスワードを入力した場合には、そのパスワードが利用されます)。

私は、はじめにユーザ名付きの URL でサーバへの接続性を確認をし、その後、~/.netrc を設定する、という手順を踏んでしまったため、どんなに正しく ~/.netrc を設定しても Password 入力プロンプトが表示され続けてしまうことになり、悩んでしまいました。

もし、.netrc を適切に設定したにも関わらず、Password を求められる状況になった場合には、リモートリポジトリの URL を確認してみてください。git remote -v で確認できます。

% git remote -v
origin http://server.example.com/sample_rep.git (fetch)
origin http://server.example.com/sample_rep.git (push)


2. 空リポジトリから clone した場合、初回 git push へは引数指定が必要

既に commit の存在する git リポジトリを clone した場合、この clone 元へローカルの変更を push する場合、特に引数を指定する必要はありません。

% git push
Fetching remote heads...
refs/
...

一方、今回のように、空の git リポジトリから clone により作成したリポジトリへ push する場合には、push 先と、push 対象の branch を明示的に指定しなければなりません。例えば、.git/config で「origin」として命名されているリモートリポジトリへ、ローカルの「master」ブランチを push する場合には、次の通りです。

% git push origin master

ただし、もちろん push する前には、ローカルのリポジトリへ何らかの commit が必要です。commit が存在しない場合、push はエラーになります

% git push origin master
error: src refspec master does not match any.
error: failed to push some refs to 'http://server.example.com/sample_rep.git'

私は git push の引数を正しく理解していなかったため、「clone 出来ているのだから、push できない筈はない」と、サーバの認証設定ばかりを疑い、時間をとられてしまいました。

空リポジトリから clone した場合、 git push へ失敗する場合には、push の引数で明示的に push に必要な情報が指定されているか、または、ローカルリポジトリへ commit が存在するかを確認しましょう。


3. 認証の失敗メッセージへ注意する

認証の必要な URL に対して git clone や push を行い、その動作が認証エラーになると、その旨を示すエラーが表示されます。

% git clone http://server.example.com/sample_rep.git
Initialized empty Git repository in /users/n-miyo/p/sample_rep/.git/
error: The requested URL returned error: 401 while accessing http://server.example.com/sample_rep.git/info/refs?service=git-upload-pack

fatal: HTTP request failed

しかし、特定条件では、一見認証エラーなのか、設定エラーなのか戸惑うエラーが表示される場合もあります。

例えば HTTP サーバの WebDAV で「clone は誰でも可能だが push は禁止する」というような、すなわち clone 時には認証は必要ない、という設定がなされていたとします。この状態で、ローカルで行った変更を push しようとした場合、例えば .netrc の認証情報が誤っていると、git push は次のようなエラーを表示します。

% git push origin master
Unable to create branch path http://server.example.com/sample_rep.git/info/
error: cannot lock existing info/refs
fatal: git-http-push failed

先ほどと異なり、HTTP のステータスコードは表示されず、lock の獲得に失敗したことを示すエラーです。一見、HTTPサーバ側でのファイルパーミション設定誤りを疑いたくなりますが、実際パーミションの設定が誤っていた場合のエラーは次のようになります。

% git push origin master
Fetching remote heads...
 refs/
 refs/heads/
 refs/tags/
updating 'refs/heads/master'
 from 0000000000000000000000000000000000000000
 to   94d642b7e985ae90956700855e158d0e885628ba
Unable to lock remote branch refs/heads/master
Updating remote server info
PUT error: curl result=22, HTTP code=403
fatal: git-http-push failed

同じくロックに関するエラーメッセージが表示されていますが、こちらは最後に、HTTPステータスコードの403(Forbidden)も示されています。

私は、「lock が獲得出来ないのは、ファイルのアクセス権が問題だ」と誤った思い込みへ陥り、本来いじる必要のない、サーバ側のパーミション設定と格闘するハメになりました。

HTTPサーバへ Apache を使っている場合、例えば、httpd-access.log を見るとこの両者の判別がつけやすくなります。例えば認証が失敗している場合、MKCOL コマンドに対するステータスコードとして 401 が返ります。

192.168.1.1 - - [07/Jan/2010:21:26:47 +0900] "MKCOL /var/www/sample_rep.git/info/ HTTP/1.1" 401 401 "-" "git/1.6.6"

一方、HTTPサーバの設定を誤って書き込めない場合には、PUT のステータスコードが 403 を示します。

192.168.1.1 - n-miyo [07/Jan/2010:21:27:04 +0900] "PUT /var/www/sample_rep.git/info/refs HTTP/1.1" 403 234 "-" "git/1.6.6"

この差を頭の片隅に置いておくと、git push でエラーになった場合、原因究明の一助にはなるかもしれません。

一度設定できてしまえば http 経由での git アクセスは、快適に利用することが可能です。
これらの情報がトラブルシュートのお役に立てばと思います。

2010/01/02

iRobot ルンバ577を購入しました

いろいろなデジタルガジェットを購入した2009年ですが、年の瀬も押し迫った12月30日、デジタルガジェットと言うには、やや家電よりの「自動掃除機 ルンバ577」を購入しました。自分で部屋の中を探索しゴミを除去してくれる、自走式掃除機です。



箱の大きさは結構大きめで、高さ55センチ、幅45センチくらい。一方、厚みは13センチ程度しかなく、普通の掃除機とはまるでちがった箱形状です。重量は約8Kgと結構重めですが、手荷物で持ち帰れないほどではありません。



箱を開くと、起動方法などの書かれた「簡単スタートガイド」が目に入ります。白物家電系機器としては珍しいのではないでしょうか。



梱包されている本体、ならびに付属品の様子。結構盛り沢山です。



中身を箱の上に出してみました。真ん中の一番大きな丸いものが本体です。本体サイズは、約33センチ、厚さは10センチくらい、重量は3.7キロぐらい。その上に乗っている黄色いものはフィルタ。最初から1枚本体へセットされていますので、これは予備用です。右端のブラシ2本も同じく予備用。



本体を充電用装置である「ホームベース」へとつなげてみました。ホームベースは写真上のほうにある黒い装置で、ACアダプタを接続します。ルンバはこのホームベースの位置を自動で検出し、掃除が終わった際、または、電池がなくなった際に、自動でこのホームベースへと接続へ向かいます。



本体をひっくり返した様子。大きな車輪が目につきます。この車輪で、多少の段差は乗り越えてくれます。右上の三本足が出ている部分がエッジクリーニングブラシで、このブラシで部屋の隅にあるゴミを掻き出します。



付属のリモコン。ルンバ577に付属しているものは、本体とデザインが統一された可愛らしいものです。





本体充電中は、真ん中のLEDがオレンジ色に、まるで、呼吸をしているかのように明滅します。なかなか、心がくすぐられます。

実際に稼働させている様子をいくつか。



ルンバは部屋の中を邁進し、壁にぶつかると向きを変えて他の場所へ向かいます。困っている様子がなかなか良い感じです。音は普通の掃除機と同じくらい。



壁のそばを進み、壁が切れたところで反転する様子。結構ぶつかっている様子がわかります。壁が近いと判断すると速度を落としているようです。



 自分でホームベースへ戻る様子。最初に流れている可愛い音は電源投入時に流れるもの。ルンバはホームベースを検出後、一定距離離れたところで反転、ゆっくりと接続へ向かいます。無事に接続できると、やっぱり可愛らしい音楽が流れます。初期ファミコン時代の面クリア時の音楽とでも言う楽曲が、「僕、うまくできたよ!」という雰囲気を醸し出し、なんとも興味惹かれます。

さて、実際に掃除機として利用した感想です。

まずは、当初私が想定していたよりもずっと丁寧に掃除をしてくれることに驚きました。私が自分で掃除をするよりも、遥かに綺麗にゴミ拾い集めてくれます。探索アルゴリズム上、掃除してくれない場所が残るのでは、とも思ったのですが、全くの杞憂でした。掃除中、モノにぶつかり「壁」と判定された箇所も、例えばそのモノを移動させることにより、再びその近辺を掃除してくれる柔軟性も持ち合わせています。

一方残念ながら、私の予想を超え、床に這っているケーブルを多くの頻度で巻き込んでしまうことも分かりました。そのため、ルンバを稼働させる前に、床に這っているケーブルは高いところへ引き上げておくか、床へ強固に貼りつけて置く必要があります。また、定期的にルンバ自体の掃除が必要になります。掃除機である以上当たり前なのですが、ゴミの中を突き進むため、それなりにゴミや髪の毛が本体へ絡まります。一方で、ロボットである以上、それらのゴミは可能な限り除去してあげなければなりません。結果、掃除機であるルンバを他の掃除機で掃除する、という少し不思議な行為が必要になります。

総じて、掃除機能は非常に秀逸で、私はルンバを大変気に入りました。平日、家を留守にすることの多い我が家では、スケジュール機能を利用して昼間の間に大まかに掃除しておいてもらい、週末に掃除が漏れている箇所を人間が手作業で片付ける、という運用でやっていこうかと思っています。これにより人間が掃除へ費やす時間を大幅に減らすことが出来そうです。

非常に実用的で、且つ、夢あふれる製品であり、大変満足度の高い製品でした。

2010/01/01

謹賀新年 2010

新年明けましておめでとうございます。



旧年中は大変お世話になりました。皆様のおかげで、大変素晴らしい一年を過ごすことができました。
本年も何とぞよろしくお願い申し上げます。

とうとう2010年、新しい10年になります。21世紀、残念ながら車は空を飛びませんでしたが、それでも子供の頃夢見た未来はだんだんと現実になっているようにも感じています。そうした大きな変化の時代を生きられることは、非常にありがたいことだな、と大変嬉しく感じている日々です。

今年が、皆様にとって、素晴らしい年となりますように!

今年もどうぞよろしくお願いいたします。