2/16, 2012

Mountain LionのMessages.appを使ってみた

Mac OS Xのあたらしいバージョン、10.8、通称「Mountain Lion」の内容がちらりと発表されました。

Mountain Lionはこういう生き物なんですが、それはさておき、今回その一部であるMessages(複数形です)が一般にダウンロードできるので使って見ました。

これはこれまでのiChat.appを置き換え、iOSのiMessageに対応させるもので、実際、Messages.appと画面には表示されますが、実態は/Applications/iChat.appだったりします。

で、感想。まだベータ版なので不都合があってあたりまえなんですが現状、日本語で使う上でこまった問題があります。なんと一つのメッセージに日本語英語が混在するとiOS上で見た時にバラバラになってしまうという問題が…

Messages.appではこのように普通に表示されるのですが…

iPhoneではこんなことに…

うーむ、これテストしなかったのかなあ。なぜバラバラになるのか、プロトコルはXMPPらしいのですが説明ができるひと、@niwまで教えてください!


以下のようなツイートをもらいました。

謎ですが、フォントをヒラギノに変えたら分割されなくなるようです。手元の環境でヒラギノにしても分割されたこともあるのでよくわかりません。

2/14, 2012

Tahoe にスノボに行って来た

まだ筋肉痛で動きが制限されています。こんにちは。

San Francisco は California 州の都市なんですが、多分カリフォルニアっていうと、こう、 海! 青い空! だと思うんですが、実は雪山もあります。

今回はそんな California 州と Nevada 州の境目にある Tahoe のスキーリゾートに遊びに行ってきたというお話。

今回はいろいろ準備が後手に回ったり、予約の過程で大失敗をしたりと色々と不手際が重なったのですが、結果的にNorthstarという Tahoe の北西にあるリゾートに行きました。

San Francisco からは只今絶賛増線中の Bay Bridge を渡ってひたすら I-80 を北上する、というコースです。昨年シーズンは渋滞で4〜5時間かかった記憶があるのですが、今回は渋滞もなく途中の Sacramento で休憩しても3時間ちょっとで到着しました。

こ、これがスキーリゾート…?!

実は Tahoe は昨年シーズン記録的な大雪で、見渡す限り真っ白でしたが、今シーズンは記録的な 雪の降らなさ で1月になってからやっと雪が降り、2月になってからは全然降っていない、みたいな状態です。 到着まで雪がちらほらとしか見えないので、さすがに途中で不安になりました。

今回は4名で出かけたので2br2ba(寝室2つ、トイレ風呂も2つ、の意味)のコンドミニアムを借りました。綺麗でキッチンとか暖炉とかもあり、いろいろ準備すればBBQとかも出来ます。

さて、その雪がないリゾートなのですが、さすがにゲレンデはバッチり雪があります。けっこうガリガリしていて、春スキーって感じでした。あ、スキーはしてませんが。

山頂からの光景。

ちなみに、日本ではスキー場では1,000円のカレーと相場決まっているのですが、米国では$10のハンバーガーとなります。California なので Tacos とかもあります。

これまでずっとレンタルだったので San Francisco に引っ越してからボードなどを買いました。ところが、昨年シーズンこのリゾートに来たときにビンディングのパーツを盗まれたり、その後遭難しかかるなど、ここは思い出深いリゾートだったりします。

写ってないけれど、右足のパーツを盗られ、その後交換パーツを送ってもらったりした関係で左右で色が違います。

今回はそんなトラブルはなく、かつリフト券を Fast Pass にしたのでリフト待ちが全くなくて非常に快適でした。これはオススメです。

というわけで、今度はちゃんと準備して今シーズンもうあと1回は行きたいなあと思っています!

2/8, 2012

Mac OS Xで動的ライブラリのバージョン違いの警告が出た

たまに、nokogiri.gemを使っているときに、

WARNING: Nokogiri was built against LibXML version 2.7.8,
but has dynamically loaded 2.7.3

と言われて凹むことがあります、というか、先日ありました。原因は多分Mac OS X 10.7.3にしたことなんですがこういう時に何をすればいいのかという話です。

nokogiri.gemlibxml2を使ったRubyのXML/HTMLパーサーなんですが、ビルド時に利用したlibxml2のバージョンを覚えていて、実行時に違うバージョンを使うと文句を垂れます。というのも特定のlibxml2はバグがアレすぎてnokogiri.gemがまともに動かないのでそれを排除する目的でそういうことをしているんだと思います。

さて、こうなった時には誰が違うバージョンのlibxml2nokogiri.gemより 先に ロードしているのを知る必要があります。普通は他のgemが明らかにlibxml2を使っていたりして、あぁ、こいつが違うバージョンのlibxml2をロードしてるのかー って気がつけることもあるのですが、まったく見当がつかない場合が問題です。

そこで、Mac OS Xで動的ライブラリのいろいろを司ってるのはdyldですが、その環境変数で便利なDYLD_PRINT_LIBRARIESを使います。詳しくはman 1 dyld

DYLD_PRINT_LIBRARIES=1 ruby a_script_requires_many_gems.rb

とすると、ロードされたライブラリがずらずら出てきますので、どのタイミングで期待してないlibxml2がロードされているのか眺めます。例えば、こんな感じ。

dyld: loaded: ... /gems/memcached-1.3.1.1/lib/rlibmemcached.bundle
dyld: loaded: /usr/lib/libsasl2.2.dylib
...
dyld: loaded: ... /Kerberos.framework/Versions/A/Kerberos
dyld: loaded: ... /Heimdal.framework/Versions/A/Heimdal
dyld: loaded: ... /Security.framework/Versions/A/Security
dyld: loaded: ... /CoreFoundation.framework/Versions/A/CoreFoundation
...
dyld: loaded: /usr/lib/libxar-nossl.dylib
dyld: loaded: /usr/lib/libDiagnosticMessagesClient.dylib
dyld: loaded: /usr/lib/libbz2.1.0.dylib
dyld: loaded: /usr/lib/libxml2.2.dylib
... ↑あっ

おや、ここでMac OS Xのlibxml2が呼ばれていますね。これが原因っぽい。じゃあこれをロードした奴は誰だってことになるので、これより上でロードしているライブラリをotool -Lで調べていきます。

$ otool -L /usr/lib/libxar-nossl.dylib
/usr/lib/libxar-nossl.dylib:
    /usr/lib/libxar-nossl.dylib (compatibility version 1.0.0, ...
    ...
    /usr/lib/libxml2.2.dylib (compatibility version 10.0.0, ...
    ... ↑あっ

ほう、libxar-nossl.dyliblibxml2をロードした犯人っぽいですね。で、

$ otool -L ... /Security.framework/Versions/A/Security:
    ... /Security.framework/Versions/A/Security (compatibility...
    ...
    /usr/lib/libxar-nossl.dylib (compatibility version 1.0.0, ...
    ... ↑あっ

ほう、Security.frameworklibxar-nossl.dylibをロードしていますね。という感じで掘り進めます。で、この依存関係を呼ばれる逆順に書き出すとこうなります。

/usr/lib/libxml2.2.dylib
← /usr/lib/libxar-nossl.dylib
← Security.framework
← Kerberos.framework
← /usr/lib/sasl2/libgssapiv2.2.so
← /usr/lib/libsasl2.2.dylib ←これはotool -Lではわかりませんが、明らかですね。
← gems/memcached-1.3.1.1/lib/rlibmemcached.bundle

なんと、お前かー! まさか、memcached.gemlibxml2をロードしているとは思いもよりませんでした。memcached.gemmemcachedのクライアントですがXMLを使う余地など無いのでパッと見さっぱりわからないですね。 多分、10.7.3でどこかの誰かがこの依存関係を創り上げたのではないかと思っていますが、今後SASL関係のやつらが全部libxml2をロードすると思うとげんなりです。

で、この場合、解決策はnokogiri.gemを素直に/usr/lib/libxml2.2.dylibを使うようにビルドしなおせばいいのですがまあ、最適解はそれぞれの状況に応じて変わるのでなんとも言えません。 というわけで、原因がわかってめでたしめでたし!

おまけ - gdbで追いかける

最初、DYLD_PRINT_LIBRARIESなんて気が付かなかったのでgdbしてdlopenでブレイクポイント立ててロードしている奴らを知ろうと思いました。結果から言えばdlopenだけではすべてのdyldのロードを見られるわけではないので失敗したのですが、忘れないようにやり方をメモしておきます。この場合は、dtraceしても良いんだけど。

ここでのポイントはdlopenはデバッグ情報がないのでそのままではgdbで引数が表示できないこと。そこでx86_64の場合、rdiレジスタから順にrsirdxrcxr8r9に引数が入ってるので、それを見ていきます。こんな感じ。

$ gdb --args ruby a_script_requires_many_gems.rb
(gdb) b dlopen  ←dlopenにブレイクポイント立てる
(gdb) r ←実行
...
Breakpoint 1, 0x00007fff93c18929 in dlopen () ←止まる
(gdb) i r ←レジスタ一覧
...
rax    0x1    1
rbx    0x7fff8cbe1000    140735554654208
rcx    0x69    105
rdx    0x9    9
rsi    0x10    16
rdi    0x7fff8cbe1980    140735554656640
rbp    0x7fff5fbfe650    0x7fff5fbfe650
rsp    0x7fff5fbfe640    0x7fff5fbfe640
...
(gdb) p (char *)0x7fff8cbe1980 ← rdi をchar *として見る。$rdi でも同じ。
$1 = 0x7fff8cbe1980 "/usr/lib/libobjc.A.dylib" ←見えた
(gdb) display (char *)$rdi ←止まるたびに出るようにする
(gdb) c ←続行
...
Breakpoint 1, 0x00007fff93c18929 in dlopen ()
1: (char *) $rdi = 0x100275210 "... /thread.bundle" ←見えた
(gdb)

便利ですね!


多分もっとかっこいい方法があるはずなので、是非@niwまで教えてください!

2/2, 2012

ドメインを移管してみるテスト

現在個人で保有しているドメインがいくつかあります。

そのうち伝統的に古い90年代に取得したある.comドメインがずーっと当時のNetwork Solutions、今のVeriSignで管理されており、その管理費用が異様に高い(年間$40くらい)なうえに、Network Solutionsのサイトが広告まみれで、なにか操作をするたびに「この機能いらない?いらない?ねえ、本当にいらない?」と聞いてきて非常にイライラするので更新時期を踏まえて移管することにしました。

移管先を探す

まず、移管先を決めなくてはいけません。条件は、手頃な値段で、うざくなくて、ある程度長い間営業している米国から使っても問題ない、.atドメインに対応している業者ということで選びました。

しかし最後の条件がキビしくてかなり絞られることになりました。最初はGoDaddyが浮かんだのですがSOPAの一件もあるのでちょっと敬遠し、結果的にNo Bullshitと言っているレジストラ、Gandiに移管することにしました。

Gandi

フランスの会社です。

移管する前にネームサーバーを変えておく

ドメインレジストラを変えるということはそのレジストラが提供しているサービスも変えるということになるので、もしレジストラのネームサーバーを使っている場合はそれを予め切り替えておかないといけません。ダウンタイムが発生してもよいのならなにも考えずに移動すればいいような気もしますが、運用されているドメイン名の場合はそうもゆかず。

ということで一旦、第三者で、簡単に設定できるAmazon AWSのRoute 53に書き換えておきます。 移管が終わって問題なさそうなら移管先のネームサーバーに再度切り替えるのでもいいですし、もし移管先のネームサーバーが事前に分かっていて、かつ設定できるのならそれを利用すればいいとも思います。

# そのドメインで使っているネームサーバー一覧する
$ dig NS ドメイン.名
...
;; ANSWER SECTION:
ドメイン.名.     165948  IN  NS  ns-....awsdns-....com.
...

Route 53はAmazonが提供するDNSサービスで名称の53はもちろん、DNSが使うUDPのポート番号に因んでいると思います。サインアップしてゾーンを追加して現在DNSに設定されているレコードを全部作ってから移管元のレジストラでネームサーバーをRoute 53のものに変更します。

Route 53

AWSのManagement Consoleからできるので楽チン。

移管申請の前にAuthorization Codeを取得

.comなどのドメインを移管するときには、移管元のレジストラでAuthorization Codeを取得して、それを移管先に伝える作業が必要です。このあたりのやり取りで重要になるのがドメインのWHOISで登録されているメールアドレスで所有者の確認に使われます。

# WHOISを見る
$ whois ドメイン.名
...
Registrant:
Yoshimasa Niwa    メール@アドレス
...

まずDomain Protectみたいな機能がある場合はそれを外して、Authorization Codeを取得します。レジストラによって手順が異なるようですが、基本的にウェブインターフェイスで完了するでしょう。

Domain Protect

費用の支払いと移管元、移管先からの確認

ここまで準備ができたら、移管先のレジストラのサイトで移管したいドメイン名を指定してAuthorization Codeを入力して移管費用などを支払います。

その後移管元、移管先双方から移管したいドメインのメールアドレスに対して「移管したい言うてるんだけどほんまかいな」的なメールが来ますので、リンクを踏んで「せやで」と答えておきます。この確認メールが来るまでに数時間を要しました。

Transfer Confirmation

移管完了

ここから待つこと数日。その日にそのままサクサク終わるかと思いきや、まったくぜんぜん。

忘れたころに移管元から移管が完了したという通知が来ます。そして移管先からも移管が完了したという通知が来てすべて完了しました。

結果的に、移管が完了するまでにさらに5日かかりましたが、そういうもののようです。ひょっとしたら手動なのかも。

1/29, 2012

Mac OS Xのパッケージファイルを操作する

Mac OS Xではアプリケーションなどをインストールするときに伝統的に.pkgで終わるパッケージが使われています。 しかし、インストールする前にどんなファイルが展開されるんだろう、とか、あのインストーラーに入ってるあのファイルだけ取り出したい、みたいなことがあると思います。

そんなパッケージにまつわる基本的な操作をまとめました。基本的にTerminal.appでの操作になります。

インストールされているパッケージの一覧

$ pkgutil --pkgs

例えば、mysqlが入ってるかなーとかは、

$ pkgutil --pkgs|grep '[m]ysql'
com.mysql.mysql

となります。[]がついてるのは、そういうgrepのテクニックです。

インストールされているファイルの一覧

既にインストールされているmysqlのパッケージがインストールしたファイルの一覧は次にようにします。インストール前のpkgに対しては後述。

$ pkgutil --files com.mysql.mysq

インストールされているファイルの削除

一応pkgutilにオプションがあったんですが(--unlink)、うまく消せないし、フォルダが残ることがあるし、なんかコマンドそれ自体がなくなった気もするので、自前のコマンドを作っています。このあたりから入手してください。 こういうのはrootで実行しますが、なんか重要なファイル消えちゃうかもなので、自己責任で。

インストールされているパッケージを消す

ファイルの削除ではなく、パッケージの登録を消す場合は次のようにします。

$ pkgutil --forget com.mysql.mysq

インストール前のパッケージのファイル一覧

どんなファイルがpkgでインストールされるか知るには、パッケージによって2種類の方法があります。まず、pkgが単一のファイルの場合(Flat Package File)は次のようにします。

$ pkgutil --payload-files path-to-flat-package-file.pkg

もし、pkgファイルがディレクトリ形式の場合は次のようにします。

$ lsbom path-to.pkg/Contents/Archive.bom

BOMってなんじゃらほいってことですが、Bill of Materialsという意味だそうです。詳しくはman bomで。

インストール前のパッケージからファイルを取り出す

これも2種類それぞれに違う方法が必要です。まず、Flat Package Fileの場合は次にようにしまう。

$ pkgutil --expand path-to-flat-package-file.pkg ./tmp
$ ditto -x --bom ./tmp/path-to-Bom ./tmp/path-top-Payload ./

pkgutilでFlat Package Fileからディレクトリに展開して、その中にあるBomを使ってPayloadファイルからファイルを取り出します。めんどくさい…

ディレクトリの場合は次のようにします。

$ pax -rzf path-to.pkg/Contents/Archive.pax.gz

また別のコマンド… なんだか様々な圧縮方法とファイル形式があって、非常に大変です。


他にもArchive.bomがない場合とかいろんな形式がある雰囲気なので、もっと良い方法があったら@niwまで教えてもらえると嬉しいです!