トップ 最新 追記

2010-01-01 [長年日記]

_ RTMをtouchのカレンダーと同期…するのは諦めてProアカウントにした

※ 書き忘れ日記掘り起こし

なんかやり方が間違ってるかもしれないし、2010-01 段階での話なので、ベストプラクティスは時とともに変わっている可能性があります。

背景というか要求

  • これまでガラケーに全部メールで RTM のタスクを通知していたが、多すぎる通知はないのと同じ状態になってしまった
    • 通常のメールを reminder と思って無視してた
  • PocketWiFi を入れて通信費をそちらに集約したいので通知も iPod touch の方に来てほしい

参考までにこれまでは

  • PC で RTM に入力
  • ガラケーに reminder メール
  • 閲覧用にみるぽん
  • どうしても出先でタスクを追加するのに Inbox アドレスをガラケーに登録

という構成だった。

選択肢

  1. みるぽん
  2. 標準の「カレンダー」アプリの通知
  3. RTM純正アプリ ( + Pro アカウント )

くらいを考えた。

  • みるぽんは試した段階で通知機能がなかった。
  • 標準のカレンダーへ RTM を直接同期することはできないっぽい
  • Google Calendar と touch カレンダーの同期、RTM と Google Calendar の同期はそれぞれ記事がある

やってみよう。

悪戦苦闘

  • Google Calendar と touch の「カレンダー」の同期は問題なくできる
  • RTM -> Google Calendar には方法が2種類くらいあるんだけど、どうしてもうまくいかない
    • 時間が掛かるという情報もあるが丸一日以上待っても反映されない

何か勘違いしてるかもしれないけど、さすがにちょっとこれはしんどい。

結論

  1. 予定の俯瞰用にRTM のプライベートアドレスを「カレンダー」から「参照」することにした
    • 予定の俯瞰はこれで十分
  2. RTM 純正アプリ ( + Pro アカウント )

本当は「参照」だけで全部解決すると思ったんだけど、「参照」だと「通知」情報が落ちてしまうので

touch で通知を受け取りたいという当初の要求は満たせなかった。

とは言え、参照カレンダーでの見やすさは今までに体感できていなかったものなので、これはこれで活用することに。

時間もなかったので「通知」は純正アプリ頼みにした。なんか負けた気がする。

今回、

  • カレンダーの「同期」と「参照」の違い
  • アプリの通知機能と iCal の通知情報の扱い

を新たに学んだ。分かってるようで分かってないことってたくさんある。

※ 純正アプリを使い始めてすぐにタスクの見やすさ、追加、編集しやすさなどかなり練られていることを痛感。これは $25/y の価値あると思う。要は手帳買うのと同じだよね。

Tags: RTM

2010-01-04 [長年日記]

_ xig_installer なんてものを書いてみた

まとめ

  • twitter を IRC に変換して使いたい
  • tig.rb を使いたいけどどこからどう入れたらいいかよく分からない
  • なんか tig.rb をもっとうまく扱いたい

人向けのツールを作ったよ。

まずはなんでこんなものを作ったのか、理由から。

~/bin になんでも突っ込むのをやめたい

現在自分の twitter 環境は

自宅サーバ上の(tiarra + TwitterIRCGateway) + クライアントPCの LimeChat

という構成になっているんだけど、実はサーバ上のプログラムは

すべて ~/bin 以下に放り込まれている状態

になっている。とりあえず動かし始めるときにはこういうのよくやるんだけど、一昨年末(!)から始めたホームディレクトリの整理の一環で、~/bin 以下も基本的に全利用ホスト共通にしたいと考えている。当然、いちばんのネックは

サーバ用の ~/bin の内容をクライアントに持ってきたくない

というところ。

gem の奥底の実行ファイルを呼ぶのがなんかイヤ

すでに書いたけど twitter への大半のアクセスに TwitterIRCGateway を使っている。ただ実はずいぶん前からこれの Ruby 派生版である tig.rb に乗り換えようとしている。

TwitterIRCGateway は自分にとって Twitter を気軽にかつディープに利用するようになるうえで絶対に外すことのできないプロダクトで、とても感謝している。

だけれど、やはりどうも FreeBSD + Mono という環境のせいなのか、

  • よく分からない落ち方をする
  • 稀に無限死亡モード(起こしても起こしてもすぐ死ぬ)に入る
  • dll の入れ替えを手動で行うアップデート方法がなんかイヤ

などの細かい不満があった。一言で言うと

どうも管理しにくい

ということである。そこで Ruby だけで動くし、gem で install できる net-irc に付属している tig.rb に乗り換えようかということなんだが、

肝心の tig.rb は gem でインストールした examples/ 以下で、gem の深い階層の下の方のファイルを呼び出すのはなんかダサイし扱いにくい*1

ということで、net-irc 以下の examples/ 以下にある *ig.rb の実行ファイル、つまり何かと IRC の Gateway として機能する実行ファイルを PATH の通ったところに install してしまうツールを用意することにした。

前置きが長くなったけど、そんなわけで xig_installer というツールを書いた。

紹介

wtnabe's xig_installer at master - GitHub

xig_installer | gemcutter | awesome gem hosting

に置いてある。

ぶっちゃけると実にくだらないツールで、gem の奥底にある *ig.rb の一覧を作り、それを gem を実行している Ruby 本体と同じパスに対して install, upgrade, uninstall するだけ。小判鮫すぎるうえにたいしたことはしてない。

でもこれだけで実行時には普通に PATH の通っているところにある tig.rb を叩けばよくなる。これが嬉しい。

使い方は簡単。

  1. Rubyをインストール
  2. Rubygems をインストール
  3. gem install gemcutter
  4. gem install xig_installer

これで net-irc も依存関係でインストールされるので、あとは

(rehash)
xig_installer install tig.rb

とすると Ruby を置いてあるパスに tig.rb がコピーされる。Ruby のインストールに管理者権限が必要なら

sudo xig_installer install tig.rb

にする必要がある。

その他の機能は

xig_install help

で確認してほしい。

tig.rb の使い方はとりあえず割愛ということでごめんなさい。

*1 gem バージョンじゃなくて git clone したものを使うでしょ、という指摘はとりあえず置いておく。


2010-01-07 [長年日記]

_ RTMの運用方法をiPod中心に変更

これまで

この夏にようやくRTMを本格的に使い出して以来、

RTMのリマインダ -> ケータイメール

で全部のスケジュールとその日一日のタスクを通知させていた。

しかし昨年末にPocketWifi + iPod touch体制に移行するに当たって、iPod touch 中心の運用に変えてケータイの方はパケット代を思い切って節約することに決めていた。

また、iPod touch にはせっかくカレンダーアプリがあるので、これで情報の俯瞰を行いたいと考えていた。ケータイにはリマインダは飛ばしていたけど結局その場限りの通知でしかなく、全体の把握には PC のブラウザが必要という状況がちょっと面白くないなと感じていた。

RTM -> カレンダー同期方法探訪

なぜか

  1. RTM -> Google Calendar ( 3rd party cookie )
  2. RTM -> Google Calendar ( private address )
  3. Google Calendar -> iPod

の情報ばかり見つかる。

1 については 3rd party cookie を許可してブラウザ上でだけ Google Calendar と RTM を連携させる方法なので、最終目的が iPod な自分としては嬉しくない。

ところが 2 がどうにもうまくいかない。時間が掛かるという情報はあったが、丸1日経っても同期される様子はないので、何かが間違っているんだろうという漠然とした予想をもとに利用を断念。

ちなみにプライベートアドレスは要するに十分複雑な URL ってだけ。

cf. Remember The Milk 日本版 公式ブログ Tips : プライベートアドレスを活用しよう

どうにもならないので、Pro アカウントにして iPhone アプリで直接同期してみた。これは確かに通知にも対応していて便利。便利なんだけど、RTM はあくまで RTM なので、カレンダー上で一覧するという使い方ができないのは iPhone アプリでも同じ。

やはり目的は

iPhone / iPod touch のカレンダーアプリで俯瞰もしたい

ということなので、これだけではちょっと納得いかない。

実は直接「照会」できた

アカウントを追加

これもしかして iPhone OS 3 以降の機能かなにかでブログ記事があまりないのかもしれないけど、実は iPhone のカレンダーは RTM のプライベートアドレスから直接 iCal 情報を読み込んで表示させることができる。わざわざ Google Calendar を経由させる必要はまったくなかった。

方法は

[ 設定 ] -> [ メール / 連絡先 / カレンダー ] から [ アカウントを追加 ]

を選び、アカウントの種類は [ その他 ] を選ぶ。

[ 照会するカレンダーを追加 ] を選んでここに iCal の URL を直接入力してやれば ok.

もちろん「照会」なのでカレンダーの編集はできないけど、今のところ RTM の Pro アカウントアプリを持っているのでそこは困らない。今後どうなるかは分からないけど、しばらくこれでいいか。

うん、やっぱカレンダーで俯瞰するとタスクリストだけでは気づけないことが分かるなぁ。

その他から照会するカレンダーを追加

というわけで Google Calendar は相変わらずうまく活用できずに2010年を迎えているのであった。なんか個人的にうまくハマらない。

通知はどうしているか

  • Google Calendar <-> 「カレンダー」同期では「カレンダ」ーの方で通知が機能する
  • RTM -> 「カレンダー」照会では通知情報が落ちるので「カレンダー」の通知は機能しない

ということで、RTM を起点にしてしまうと「カレンダー」の「通知」は機能しない。

  • RTM Pro アカウントアプリで独自に通知できる

のだけど、いずれにせよ RTM の「リマインダ」がキーになる。まぁ以前のようにメールが来まくって、どうせ RTM の通知だなと思ってその他のメールのチェックが疎かになってしまうよりはアプリの通知の方がいいんだけど、iPod touch にはバイブがないし、普段ボリュームを上げまくっているわけでもないので、意外にこの通知に気づかない。

結局、本当に大事な時間はケータイのアラームやスケジュール、常用 PC 上の Lightning や cron + growl など、補助ツールを使うことにした。若干手間は増えたけど通知が多すぎて疎かになってしまうよりはマシかなと思っている。

ついでに他のも照会している

イントラのカレンダーも必要なものは入れてしまうことにした。結局いくつカレンダーがあっても自分の時間軸は一つしかないので、必要な情報は全部手元にないと意味ないなと思った。

うん、いい感じ。

Tags: RTM iPod

2010-01-08 [長年日記]

_ OSX 10.4 で ffmpeg を使う 2010

2009年の振り返りを華麗にスルーした wtnabe です。いや、そのうち振り返ろうとは思ってますよ。マジでマジで。

話変わって今回もまたなんでそんな今さらなネタ!?という内容です。

結論 - macports の ffmpeg で ok

結論を先に言うと OSX 10.4 でも MacPorts (1.8.2) から ffmpeg (0.5) をインストールすれば*1 MPEG2 から DV へ変換でき、正しく QuickTime に解釈させて iMovie に取り込むことが可能になります。

ではその顛末をどうぞ。

背景 - 古めの iMac でビデオ編集

去年からちょこちょこ仕事でムービーの編集とか DVD のマスタリングを行っています。仕事とは言え売りもんを作ってるわけじゃなくて、あくまで内部保管目的ですが。で、カメラとか HDD の容量の問題がいろいろあって、この作業を

古めの Intel iMac (OSX 10.4 + HDD 160GB + iMovie HD 6)

で行っております。で、これまではカメラが DV だったので iMovie で取り込むだけでよかったんですが、MPEG2 で撮れるカメラからデータだけ持ち込まれる、というケースが発生。まぁ今どきのカメラなら MPEG2 とか MPEG4 とか当たり前ですね。でもこれは困る訳です。

iMovie は MPEG2 を編集できません。

しかもカメラ直結で iMovie に取り込めるんならいいんですが、データだけ渡されてしまうのです。

ffmpegX が動かない!

あーじゃあ ffmpeg で変換ね、ということで

ffmpegX a DVD, SVCD, VCD, CVD, VOB, DivX, XviD, H.264, PSP, iPod, MP4, MOV encoder for Mac OSX

から落として実行。(バージョンは 0.0.9y)最近は英語環境作らなくても ffmpegX で変換できて便利だよねーなんて思っていたら、

ffmpegX がソース movie の判別に失敗する

じゃないですか。えーっ。元のムービーが何か分からなければ正しく変換できるわけないやん。もしかしたらと思って一つ前の 0.0.9x を試してみましたが現象は一緒。

制限

ちなみに OSX 10.5 (PPC) + 0.0.9y で意図通り MPEG2 -> DV 変換を行えるのは確認済みであります。

じゃあその変換できる機械でやりゃいいじゃんと思うかもしれないけど、この PPC マシンは自分のメインマシンだし何より遅いのです。Windows マシンはあるのでそれで変換するという方法もなくはないけど、Windows マシンは HDD にまったく余裕がなく、さらに DV に変換しちゃったでかいデータを編集作業用の機械に持って行くのも一苦労な環境なのです。

笑え。

ffmpeg そのものを試すがコンパイル済みのものはダメ

GUI なんかなくたって変換さえできりゃいいよと思い立ち、ffmpegX のパッケージの中を覗いて ffmpeg コマンドを直叩き、すると変換の実行を試みるがほどなく落ちるorz 一つ前の 0.0.9x 内の ffmpeg コマンドは 0.0.9y のものよりは保つが、やはり途中で落ちるorz

いざ MacPorts へ

八方ふさがりかと思いかけたけど、これ IntelMac だし、もしかしたら MacPorts に ffmpeg あるかも、と思ったらこれがビンゴ。よーしということでここから以下の手順を踏むことになります。

  1. install DVD から XCode Tools をインストール
  2. The MacPorts Project -- Home からMacPorts をインストール
  3. sudo port install ffmpeg
  4. mp4v2 がコンパイル不能。どうも生成される Makefile がおかしいらしく、#21007 (mp4v2 build fails on Tiger (libtool: more than one: -current_version option specified)) &#8211; MacPorts から patch を取ってきて当てる
  5. libtheora に install DVD から入れた XCode は古いから上げれと言われる。ADC から 10.4 に入れられる XCode 2.5*2をダウンロード*3 -> インストール
  6. 全部インストールできた!

ここで初日は時間切れ。

QuickTime が解釈しない!

無事インストールできた ffmpeg で変換を試みる。えい。おぉ、変換できてるできてる!

……。

あれ?

変換済みの dv ファイルを QuickTime で開くといきなり「ファイルの最後に達しました」と言われる。もしかして変換後のデータ壊れてる?

ffmpeg は target ごとに default bitrate をよしなにしてくれない

試しに VLC で開くと再生できる。…けど。なんだこの荒さ?

あー bitrate の問題なのね。man を見ると確かに

      Video Options

      -b bitrate
          Set the video bitrate in bit/s (default = 200 kb/s).

って書いてある。target フォーマットは DV だって言ってるんだから DV 用の bitrate にしてくれりゃいいのに。

というわけで

ffmpeg -i foo.mpg foo.dv -target dv -b 25000k

で変換したら QuickTime で読めたよ!

QuickTime で読めるということは iMovie に取り込めるということ。いやーめでたしめでたし。長い道のりだった。

Tags: Movie OSX

*1 この道のりも平坦ではありません

*2 over 900MB

*3 約30分


2010-01-09 [長年日記]

_ iPod touchからのdelicous post復活

FLDR の pin を purge するときに delicious に投げられないと困るのだが、いつからか、それ以前には動いていたはずの bookmarklet が動かなくなって、なんでだろうなんでだろうと思っていた。ちゃんと注意して delicious を利用する記事を読み直していたらアプリのことが書いてあった。

何のことはない、必要なアプリを意図せずアンインストールしていただけだった。そうか、Mobile Safari だけで bookmarklet を動かすことはできないのか?

以下、昨日*1の Twitter のログ。

22:35:11 >wtnabe< できた。何もかも解明。1) 長いこと iPod touch で
delicious に投げられないと思っていたのは必要なアプリをアンインストール
していたから。
22:36:44 >wtnabe< 2) これは、アプリのインストールとbookmarkletの設定を
非同期に調べて非同期に実行したため、bookmarklet の実行にアプリが必要と
いうことがまったく分かってなかったから。アプリの名前は Delicious
Bookmarks
22:37:21 >wtnabe< 3) なぜあるときこれをアンインストールしたかというと、
これはブックマークの同期に時間が掛かりすぎてこけてしまうことがあったた
め、同期目的では Yummy を入れたから。
22:40:44 >wtnabe< ということで同期の設定を切ってbookmarklet動作用アプ
リとして復帰してもらった。なんかちょっとアホくさいけど仕方ないな。

ということで

Yummy
同期、参照用
Delicious Bookmarks
bookmark post用

の2アプリ体制になってしまった。

cf.

DeliciousのiPhoneアプリ"Bookmarks"でどこでもブックマークできるようになった - Blog.IKUBON.com

*1 日記の日付上


2010-01-12 [長年日記]

_ 実行中の Ruby の install ディレクトリを知る

xig_installer のために実行中の Ruby のパスを知りたいと思ったが、当初は方法がよく分からず、とりあえず放置していた。これをちゃんと調べ直した。

ENVじゃなかった

2010-01-07
17:05:43 >wtnabe< ruby -e 'p ENV["_"]' って自分自身を実行している
Ruby インタプリタを得る方法という理解は合ってますか?
17:14:06 <eban> @wtnabe 合ってないです。bashとかが設定してるので、shだ
とだめ
17:35:11 >wtnabe< @eban あざっす。ちなみに純粋に Ruby スクリプトだけで
知る方法ってあるんですかね?

ごそごそ調べると require 'rbconfig' が必要らしい。

2010-01-08
11:15:51 >wtnabe< 実行中の Ruby のパスは ruby -e 'require "rbconfig";
p Config::CONFIG["bindir"]' ですか?

Config -> RbConfig 移行問題

2010-01-12

18:56:55 >wtnabe< Ruby 1.8 は Config で 1.9 は RbConfig なのか。えーと
どう書けばいいのかな。
19:00:59 <znz> @wtnabe ConfigでもRbConfigでも見えるからどっちでもいい。
もうサポートされてない古いのも対応したければConfigしかなさそうだけど。
19:10:01 >wtnabe< @znz Config はいずれ廃止予定とかではないんですかね?
個人的には 1.8.5 以降だけ相手にすればいいのでギリギリどっちでもオッケー
なんすけど。
19:12:59 <znz> @wtnabe 廃止予定だと思うので、新しいのだけで良ければ
RbConfigがいいのではないかと。
19:12:59 <nsiena> @wtnabe require 'rbconfig' 後に定義状況を
const_defined? で調べて RbConfig = Config とかではだめです?
19:14:29 >wtnabe< @nsiena あーそんなんでいいですね。ありがとうございま
す。

まとめ

最終的に出来上がった部分がコレ。

require 'rbconfig'
RbConfig = Config unless defined? RbConfig
RbConfig::CONFIG['bindir']

cf. Commit 651136d20e9925d9a86d224272acae13dad84c31 to wtnabe's xig_installer - GitHub

RbConfig は Ruby 1.8.5 以降で定義されているので、まぁ現役で使われている Ruby のほとんどはわざわざこの書き方にしなくても RbConfig を読めば大丈夫だと思う。

参考

ちなみにちょっと前にこんな議論があった。インストールディレクトリではなくて実行パスだけど、 basename 噛ませばいいだけだし、似たようなもんかと。

MarkMail って使いやすいなぁ。すごいなぁ。

Tags: Ruby

2010-01-13 [長年日記]

_ lftp mirror でドットファイルを対象にする

以前作った簡単なWebサイト向けRakefile で lftp mirror を使って一部のサイトの更新をしてるんだけど、ドットファイルが正しくミラーリングの対象になっていなかったので、この問題を修正した。正確には

全部アップするときにはドットファイルは対象になるけど、remote の list を取得するときに無視されてしまうので、問答無用でアップするだけで、local で削除しても反映されない。

という状態で、これは具体的には

.htaccess で認証を掛けていたものを外すことができない

というかなりおバカな状態になっていた。これへの対処は

set ftp:list-options -a

と設定を変更するコマンドを与えること。細かい方法はリンク先の Rakefile を grep してもらうとして、基本的には

lftp -e 'set ftp:list-options -a; mirror --delete FROM TO; bye'

って感じで使う。

うん、これで安心して使えるようになった。

_ ngrep で localhost 宛のパケットを覗く

みんな大好き ngrep. でも ngrep はそのままでは localhost へのアクセスの様子は抽出できない。man にはこのように書かれているので、

-d dev By default ngrep will select a default interface to  listen  on.
       Use this option to force ngrep to listen on interface dev.

例えば

sudo ngrep -d lo port 80 (Linuxはこうだと思う)

とか

sudo ngrep -d lo0 port 80 (BSD系はこうだと思う)

とすれば localhost に立てた Apache への通信の様子をみることができる。

ちなみに default interface の決まり方、localhost を意味する loopback interface についている名前、これらは使っている OS によって異なるので、実際にどうなっているかは各自で調べてちょ。


2010-01-14 [長年日記]

_ Ruby の SSL の証明書検証の失敗でハマっていた

基本的な流れ

  1. TIG から tig.rb に移行しようと思い立った
  2. tig.rb が先日の DNS 障害の件を受けて SSL の証明書をちゃんと検証するようになった
  3. 自宅サーバの FreeBSD 上の Ruby で CA証明書が認識されておらず、結果 twitter.com のサーバ証明書を検証できずにコケていた。

tig.rb のアップデート - 冬通りに消え行く制服ガールは、夢物語にリアルを求めない。 - subtech

を読む前にハマってました><

だらだらと言い訳

  1. 本番と検証で3種類のRubyを使っていた
    • ports ( Ruby 1.8.7 ) on FreeBSD
    • MacPorts ( Ruby 1.8.7 ) on MacOSX
    • Fink ( Ruby 1.8.6 ) on MacOSX
  2. ports のものだけ証明書がインストールできてなかった
  3. たまたま ports のものだけ tiarra と組み合わせていたので tiarra にあらぬ疑い
    • ここでしばらくハマる
  4. 最終的には RFC と tig.rb の中身を読んで tiarra を除外、エラーメッセージを検索して Net::HTTP に矛先が

最初はバグを疑った。

14:25:09 >wtnabe< http://bit.ly/4tHhtN この patch 適用したら
OpenSSL::SSL::SSLError 例外に出会えた。

このパッチを当ててみた。すると OpenSSL 周りの例外が出てきたので、とにかく SSL の問題だということで落ち着く。tig.rb を読むと SSL の verify_mode をセットしている部分があったので試しにこれを外してみたら動いた。

Twitter / wtnabe: さっきのパッチ当てた状態で tig.rb を htt ...

14:38:26 >wtnabe<さっきのパッチ当てた状態で tig.rb を
http://gist.github.com/276924 こうしたら動いた。ここまできて残りは証明
書か。とりあえず tiarra のせいでもなんでもなかった。

Twitter / wtnabe: net/http を元に戻しても動いた。ということで ...

net/http を元に戻しても動いた。ということで openssl で使う証明書の問題
だった。もしくは tig.rb で証明書をまともにチェックしないようにしちゃう
か、どっちか。

この状態で Net::HTTP を元に戻してみたがやはり正常に動作した。ということは本当に単なる SSL の問題。

その後、

Twitter / : @wtnabe tig.rb動かしてるのがFreeB ...

18:18:54 <otsune> @wtnabe tig.rb動かしてるのがFreeBSDだったので
security/ca_root_nssいれた

と @otsune に情報をいただいたので、security/ca_root_nss を入れたけど、うまく動かず。最終的にはインストールされていたパスの問題で、

Twitter / wtnabe: VERIFY_PEER でも /usr/local/ ...

00:05:34 >wtnabe< VERIFY_PEER でも /usr/local/openssl/cert.pem@ ->
/usr/local/share/cert/ca-root-nss.crt の link で動いたっぽい。

ということで tig.rb を元に戻して link 張って解決。長かった!

結局、インストールしていた証明書を正しく認識していなかっただけ。でも Net::HTTP のエラーの出方も分かりにくいよねぇ?

ちなみに他にもハマっていた人が。

Twitter / Yugui (Yuki Sonoda): このRubyはどのOpenSSLとリンクされるんだー ...

※ Ruby 1.9 の方は Ruby 1.9 - Feature #2579: Net::HTTP.start("www.ruby-lang.org", use_ssl: true) で SSL 利用を可能に - Ruby Issue Tracking System で証明書の検証をデフォルトで行うようになる新 API が入りました。

残り関連のログをコピペ。

2010-01-15:12:05:40 @yugui favられてたのでちょっとまとめる時間を端折っ
てお伝えしますと、RubyのNet::HTTP.new()はSSLの検証に失敗したときに
@socketがnilのままになるんだけど、考慮されてないパターンがあるという問
題でした。
http://groups.google.co.jp/group/linux.debian.bugs.dist/browse_thread/thread/27dae518c1c5d617
2010-01-15:12:19:11 @yugui SSLの検証失敗をどうやって知るのか、という意
味では.request()がnil.closed?()になってしまうとか、あるいはinspectした
ときのopen=falseだけだとちょっと分かりにくいかなとは思います。
Tags: Ruby Security

2010-01-15 [長年日記]

_ God + tig.rb へ移行した

ありがとう TwitterIRCGateway

Twitterに日常的にアクセスするようになってから、ずっと IRC に変換して利用しています。何度かあちこちに書いてる気がするけど、個人的には IRC と Twitter は繋ぎっぱなしで気が向いたときだけ見るとか、呼ばれたことに気づいたときだけ返事する、という使い方がとてもよく似ていると感じています。そしてこの接し方は自分への負担がとても少ないのです。だから自分の中ではまだしばらくはこの使い方以外想像ができません。

この IRC への変換にはずっと TwitterIRCGateway を利用してきました。ありがとうございます。Twitter を通じて交流が広がったのは間違いなく TIG のおかげです。

FreeBSD + Mono + TIG は少々気難しかった

そんなお世話になりっ放しな TIG でしたが、自宅サーバ上で動かしているため、

FreeBSD + Mono + TIG

という構成になってしまいます。これがやはり少々気難しいのですね。その辺の話は xig_installer なんてものを書いてみた にも書いたのですが、もともと .NET がよく分かっていないこともあって、

  • いつ落ちるのか分からない不安
  • 何が悪いのか、何を直せばいいのかよく分からない不安

がずっとあったのは確かです。まぁ、TIG が落ちようが Twitter が落ちようが、そんなに困らないことはすでに分かっていたんですが(笑)

そこで構成を変えようと、実はずいぶん前から思っていました。

こんにちは God + tig.rb

以下、やったことへのリンク。

実は自分の使っていた IRC クライアントとの相性の問題で乗り換えられなかった時期も長かったのですが、今は LimeChat + tiarra でまったく問題なく使えています。快適です。

tid がめっちゃ便利

その後、分かったことです。

なんで irc クライアントで Twitter 的に正しい reply を打てるのか不思議だったのですが、

  • tig.rb 上で、twitter の status id と紐づけられる id が生成される
  • tid というのはどうも typable map id の略っぽい?
    • (あるいは tig.rb id ?)

こんな風に irc クライアント上に表示されます。

wtnabe アイディア出しするときは広い画面が欲しくなるなー [ipya]

ちょっとよくあるフッタと区別がつきにくいように見えますが、実際には(対応していれば)色分けされているので、そこまで見にくくはないです。

これを使って

/me reply <tid> HOGE

って打つと irc クライアントから in_reply_to を付加して reply できます。こんな使い方。

/me reply uno 簡単な言葉の吐き出しと並べ替えに OmniGraffle を使ってる
のです。そのまま整理していくのにも便利だし。面倒なことを考えるときは手
書きになります。

すると他の Twitter クライアントから見てもちゃんと繋がりの分かる reply を打てます。今までの自分の reply には ID がついてなくて見にくいなと思っていた方々、ごめんなさい、今後はたぶん大丈夫です。

同じ要領で

/me fav <tid>

とすることで fav れるので、irc クライアントから目も手も離さずに twitter 上に self fav のメモ書きを作っていけます。実はこれがかなり便利。

TIG にもこの機能は入ってるっぽいんですが、よく分かってませんでした。でも調子に乗って self fav ってばかりいると後でまとめるのが大変なので、そこは考えどころですね。

Twitter が落ちてても困らないとか書いていながら Twitter に必死になりすぎじゃね?と思ったかもしれませんが、今まで挙げたやつ、全部他にも応用が利くからいいんですよ!


2010-01-18 [長年日記]

_ 作業の自動化の次は作業の記録

とりあえず思いつきのメモ。

rake, capistrano を知って以来、単なるスクリプト化よりも分かりやすく扱いやすい作業の定型化、自動化を意識してきたんだけど、次はこれの記録かなと思っている。まぁ、現状はそれほどタスクの shlauncher 化が進んでいるわけじゃないんだけど、それはまた別な問題。

記録ということはログなんだけど、どこに記録するかというと、やっぱ一つHTTPサーバを用意して投げつけるのが楽ちんかなとか妄想している。Sinatra 辺りでフロントを用意して、実際にはほとんどログの蓄積とその検索以外に仕事のないアプリがあると便利なんじゃないかと思う。

問題はこのログの形式で、前々から全文検索に興味がありつつ手が動かせていないので、何か適当な全文検索エンジンを使いたいな、くらいの軽い気持ちでいる。以前なら HyperEstraier 一択くらいの気持ちだったけど、今はフォーマットを自由に決められそうな Ferret がいいのかなと思っている。

RDBMS と連携するツールでもいいんだけど、個人的にはログと RDBMS は相性が良くないと思っているので、ログはプレーンに用意してインデックスを別に用意する方法を採用したいかな。いざとなったらとりあえず grep だけでも使えるしね :-P

記録の部分を分離してあれば GUI アプリでも CLI アプリでも楽に記録をとれるんだけど、基本的には shlauncher ベースで考えたいと思っている。

以上。まだ何も書いてないよ!

Tags: Sysadmin

2010-01-19 [長年日記]

_ Godにプロセスの起動順序を教えたい

起動順を制御したい背景

先日、God + tig.rb 環境に移行したわけだけど*1、実際には自分の irc 周りの環境は下の図のようになっている。

               twitter
                   |
               internet
                   |
      +----+   +---+--+
      |ircd|   |tig.rb|
      ++--++   +---+--+
       |  |        |
    +--+  +-+  +---+
    |       |  |
+---+--+  +-+--+-+
|nadoka|  |tiarra|
+------+  +---+--+
              |
   LimeChat ( Mac or iPod )

拙い図だけど四角で囲んである部分は自宅サーバ内で動いているプログラムである。制御したいプログラムだけ抜き出すと、

tiarraproxy
nadokabot
tig.rbtwitter gateway

という構成になっている*2

そしてここからが大事なんだけど、

起動の順番としては tiarra がいちばん最後

である。

God 以前

God 化する前、これらは単に sh スクリプトから順番に起動するだけだった。

nadoka
sleep 2
tig.rb
sleep 2
tiarra

である。サーバサーバなんて偉そうに言っといて中身はこんなもの。途中で何かの拍子にどれかのプロセスが落ちたらそれだけまた起こし直す。全部手動で、厳密には daemon プロセスではなく

ただずっと起きっぱなし

の状態になっていた。サーバ管理的にはあまりに稚拙だが、こと起動順に関しては

書いた通りの順番に起動する

という分かりやすいものだった。しかし God 化してしまうとこうはいかない。

God の起動の流れ

0.8.0 で確認したところ、以下のようになっている。

  1. God.watch の指定を読み込めるだけ読み込む
    • watch の name を key にとる Hash に放り込まれる
  2. 読み込み終わったら Hash から一つずつ取り出し、autostart を指定してあったら(default で true)ただちにプロセスの起動を行う

ということは少なくとも Ruby 1.8 では

God.load の読み込み順、God.watch の出現順とプロセスの起動順は無関係

である。

はて困ったな。

無理矢理解決してみた。

ここでは単にプロセスの起動順序だけを問題にしたいので tiarra や nadoka など実際に使ったプログラムではなく、先日の xig_installer で動かしやすくなった tig.rb と wig.rb で試したみた。

上の gist のファイルを適当な名前で保存して

god -c CONFIG

で起動すると

必ず wig.rb の方を後で起動することができる。

順番は

ps ax | grep ruby

して PID を確認すると分かる。

ポイント

  1. あとから起動したいものの God.watch の記述の中で autostart = false を加える
  2. watch 定義のあとに Thread.new {} の中で無理矢理待ちたいプロセスの起動を待つ

待ちたいプロセスの様子は God.status[NAME][:state] で確認することができる。

実は、こんな書き方でいいのか分かってない。本当はもっといい書き方、正しい書き方があるのかもしれない。探したけどまだまだ God の情報は少ないし、英語になるとどういう言葉でこれを探せばいいのかも分からない。

でも目的は達成できている。

参考 - God.load の流れ

God.load は指定された設定ファイルを読み込むものなんだけど、内部で Dir.glob を使っているので一つずつファイル名を指定しなくても

God.load File.dirname( __FILE__ ) + '/*.god'

なんて書き方でまとめて読み込むことができる。最終的には Kernel.load が呼ばれるので Ruby の文法に則っていないと、この時点で弾かれる。

最初、読み込み順でプロセスの起動順を制御できるかと思ったけど違ったのでこの部分の読み込みはあんまり活かしようがないのであった。残念。

*1 現時点ではその日記は書いてないです!

*2 本当は ircd も含めて制御すべきだと思うけど、まだやってない。


2010-01-20 [長年日記]

_ Godで簡単daemonize

今さらながら

なぜ daemontools を使うのか - kazuhoのメモ置き場

これを読んで、

通常のプログラムをそのままデーモン化できるから

という記述にうんうんと頷いていた。*1

今回は、daemontools もいいかもしれないけど God を使って daemon 作ろうぜって話。これは monit には真似できないよ。

cf. M/Monit | Wiki

Godでオレオレデーモンを作る

例えば以前作った Rswatch っていうログを監視するツールなんかも、一応 daemon のように動くけど、これ落ちたらどうすんのとか、システム起動時に自動的に起きるようにするのどうしよう、とかいろいろ管理しにくくて仕方なかった。デーモンを作ることは、実は 1)目的の動作を作り込むこと、2)デーモン化する処理を作り込むこと、の二つに分けられる。そう、2 は目的じゃない。期待する動作ではあるけれど。

God を使えば 2 の部分はすべて God 任せにできる。

また自分の中では daemon と言うとサーバとかこういう監視ツールをすぐに思い浮かべちゃうんだけど、別にそんな役に立つものばかりが daemon というわけじゃない。ここでは

とりあえず終了しないもの

は全部 daemon と呼ぶことにする。例えば twitter の bot なんかは daemon である。

Godを使った基本的なdaemon化の流れ

実は Ruby だけの話であれば別に God を使わなくても Process.daemon でも daemons でもいいのだが、これは後述することにして God の話を進める。

スクリプトを用意

まずは終了しないプログラムを作る。こんなものでもいい。

#! /usr/bin/env ruby

require 'logger'
 
i = 0
l = Logger.new( File.dirname( __FILE__ ) + '/counter.log' )
loop do
  l.info( i )
  i += 1
  sleep 1
end

これを例えば counter.rb という名前で用意する。これを実行すると当然1秒ごとに延々と数字を数え上げていく動きをする。

tail -f counter.log

で、その様子を確認できる。わざわざ絶対パスにしているのは、

daemon 化したときにカレントディレクトリが変わってしまうから。

これはもうそういうものなので肝に命じておく。

godファイルを用意

同じディレクトリに以下の内容で God の設定ファイルを作る。

God.watch do |w|
  w.name = 'counter'
  w.interval = 5.seconds
  w.start = "ruby #{File.dirname( __FILE__ ) + '/counter.rb'}"
  w.behavior( :clean_pid_file )

  w.start_if do |start|
    start.condition( :process_running ) do |c|
      c.running = false
    end
  end
end

これを counter.god のような名前で保存する。スクリプトのパスを絶対パスにしているのはさっきと同じ理由。あるいは実行するプラグラムを PATH の通ったところに置けばもう少し話は簡単。

xig_installer を作ったのは実はこのためである。

実行ファイルの場所が変わってしまったら God の設定ファイルをいちいち書き換えなくてはならない。これは面倒くさいし、まず忘れる。

※ ここでは ruby に PATH が通っていることを期待した書き方になっているが、FreeBSD + ports のようにデフォルトの PATH が /usr/bin で追加するプログラムがすべて /usr/local/bin に入る環境は、この部分もフルパスにしておくべき。

god 経由で起こす

まず -D を付けて起こす。

god -D -c counter.god

するとスクリプトを daemon 化する様子、状態を監視している様子がそのままターミナルに表示される。正常に daemon 化できて監視できていれば ^C で終了する。

このとき、daemon 化したスクリプトはそのまま動き続ける

が、慌てず

god -c counter.god

と打って god プロセスの daemon 化を行う。すると

今動いているプロセスをそのまま監視対象にできる

ので、この状態で

god stop counter

と打てば止められる。あるいは

god terminate

とすれば丸ごと全部終了できる。

どうだろう。

単に終了しないプログラムを作っただけなのに God を噛ませることでちゃんと daemon 化できている。*2

また、ここまでの例はすべて Ruby で書いているが、daemon 化したいプログラムは何で書かれていても関係ない。Godにプロセスの起動順序を教えたい などで触れている tiarra は Perl 製だし、なんでもよい。

おまけ - Rubyでdaemonを作って管理するその他の方法

死活監視やリソース消費を監視して自動的に再起動、などの機能が要らない場合は以下のリンク先も参考になる。

ただしこれらの情報だけでは作った daemon をコントロールすることができない。Rubyスクリプト限定でいいなら以下を使うと God より楽に管理できる。

これを使えば基本的には

Daemons.run(デーモン化したいスクリプトのファイル名)

だけで済む。

ま、もちろん監視はできないけど。

*1 本当に理解できているか自信がなかったのでブログのコメントでその確認もさせてもらった

*2 細かい daemon の定義は調べるといろいろ出てくるよ!


2010-01-21 [長年日記]

_ rqr を使って Ruby で QRCode 画像を作る

[2014-05-02 追記] ここで書いている rqr は基本的に Ruby 1.8 用でした。その後アップデートされている可能性はゼロではありませんが、1.9 でも動くように自分で

wtnabe/rqrcode_png_bin

を書いてそちらを使っています。興味ある方はどうぞ。


さぁ、今さら日記シリーズが復活しましたよ。

QRCode 画像を Ruby で作る

QRコードを算出する部分は ext だし、画像を吐き出す部分はネイティブのライブラリに依存しているので、多少準備が面倒だけどたぶんそれなりの速度が期待できる。

実は以前から one-liner なんかで使ってはいたんだけど、改めて定型作業に使えるようにちょっとしたスクリプトを書いてみた。

で、そのときに気づいたんだけど、これ、サイトのサンプルコードが間違っている。

RQR::QRCode.new
RQR::QRCode.create

が同じように動くように書いてあるんだけど、new の方は block は受け取らない。create の方は block を受け取って close するまで全部まかなってくれる。あと、Windows 版で面白くない動きをする。

2009-10-14 の twitter のログより。

14:34:29 >wtnabe< あー rqr 0.2.2 は Windows でバグってるのか
14:48:53 >wtnabe< 分かってきた。RQR::QRCode.new.save だと怒られる。
RQR::QRCode.new { |qr| qr.save } だと大丈夫。でも close がないって怒ら
れるのはちょっと不安だなぁ。

ということで create 使っておくのがいちばん無難なのかな。Windows でなんか文句言われるのは今のところ握りつぶしておくしかないみたい。

※ なんか、咳さんが非gem環境でインストールしてる。

画像が必要ない場合は他の方法でもいいけど

実はもう Web 上に QR コードを表示させるためだけならこういう画像を生成するツールはなくてもよかったりする。なぜなら JavaScript があれば動的に生成できるから。

でも例えば印刷用に画像を用意したいとかいう場合はやはり「画像」を自動生成する方が楽。実際にはこの rqr だけでは細かい調整をするのは大変なので、ImageMagick などを噛ませる必要があると思うけど*1

Tags: Ruby

*1 実際、件の ImageMagick のオプションを調べたのはこのため。


2010-01-22 [長年日記]

_ イントラgem server運用開始

2009.10.29

09:14:00 >wtnabe< gemcutter サーバをイントラに立てられると便利だろうな

2009.12.03

21:14:52 >wtnabe< イントラに gemcutter サーバがあると便利だよね

酒を飲んだとかでなく、平気で同じことをくり返し言うようになってきている。まいりましたな。

それはともかく、gem server が簡単すぎてビビる件 を書いてから知らん間にずいぶん時間が経ってしまったが、やっと活用し始めた。

2010.01.22

11:37:34 >wtnabe< イントラに gem push したいしたいと思ってたけど、とり
あえず Rakefile に scp する task 足した。permission を考えたくないから
DAV 経由にした方がいいかなぁ。

どうしたかというと、cutagem で作った Rakefile に直接こんな task を書き足してお茶を濁した。我ながらひどい。

desc "push gem to intra gem server"
task :push_gem do
  name = "#{NAME}-#{VERS}.gem"
  sh %{scp name HOST:/PATH/TO/GEM_SERVER/gems}
end

こんなん。サーバ側では

/etc/cron.hourly/generate_gem_index
#! /bin/sh

GEM_ROOT=/PATH/TO/GEM_SERVER

gem generate_index -d $GEM_ROOT
chown -R Webサーバにしたんだっけ $GEM_ROOT

こんな感じで回してる。

scp で投げるのやめて DAV で投げられるようにすれば権限とか owner とか面倒なこと考える必要なくなるような気もするけど、あんま考えてない。どうせしばらく自分しか push しないだろうし。

あとはイントラで他に動いてるホストの

/etc/gemrc

に、ひっそり

:sources:
  - http://HOST/PATH

で、gem を探すサーバを書き足してやる。

ちなみにイントラのgemはライブラリではなくshlauncherで固めたツール群の配信を想定している。

Tags: Ruby RubyGems

2010-01-24 [長年日記]

_ freebsd-update で 6.4-RELEASE に

自宅サーバの FreeBSD は基本的にはお気楽実験用なんだけど、DNS cache サーバを兼ねているので事故るとまずい。そういう意味も含めて古めのものを追っかけてるんだけど、今まで使っていた 6.3 が 2010年1月いっぱいでサポートされなくなるので 6.4 に上げた。

freebsd-update

手順はこんな感じ。

freebsd-update -r RELEASE upgrade
freebsd-update -r RELEASE install
shutdown -r now
freebsd-update install

library が上がって ports 上げろって言われたので以下の作業を追加。

portupgrade -af
freebsd-update install

念のためもう一度再起動しといた。ports の full rebuild は途中で設定を何個か聞かれながらで丸半日以上掛かったかな?

そうしたら ircd-hybrid, nadoka, tiarra の起動周りがイマイチ、nadoka がうまくいったりいかなかったりしてる。もしかして nadoka が ircd より先に起きたりしてるのかもしれない。どうにか手動で順番もきっちり意識して再起動して意図した動きに。やっぱ ircd も God 管理にしなきゃダメだなぁ。

Trac が 0.11 で動かなくなった

※ 解決済み。なぜか mod_fastcgi が無効になってた。これを戻しただけで動いた。

Trac, pysvn 周りはいつもちょっとハマるので面倒で放置していたんだけど、portupgrade -af で一緒に上がってしまって案の定動かなくなった。

どうも PYTHON_EGG_CACHE が設定できていなくて cache を作るディレクトリが見つからないみたいなんだけど、

Apache + FastCGI

で動く設定が出てこない。なんか FastCgiConfig --initial-env じゃなくて PythonOption で渡すみたいなんだけど、edgewall の方にキチっと書かれてないなぁ。Python 読める人が自力で解釈してブログに書いてあるのはありがたいんだけど、0.11 が出てずいぶん経つのに情報が整理されてないのは Python 製のツールっぽくない印象。

とりあえず自宅で Trac は重要じゃないから今度考えよう。


2010-01-26 [長年日記]

_ Mechanizeで無茶をする

mechanize-0.9.3 Documentation

自分にとって Mechanize による自動化はたいがい無理を通す行為である。分かりやすく言えば API なんかない、あるいはあっても足りないみたいな状態で、それでもどうにか自動化したいから Mechanize を使う。

Mechanize が持っている標準的な機能だけで済んでいる場合はまだかなりマシで、実際のところ無理というか「無茶」なレベルに突入してしまうことが、なぜかそれなりにあったりする。具体的には HTML が壊れているのでパースに失敗して、あるはずの要素がなくなっていたりする場合などである。

今回はそんな無茶の一部をご紹介。

パーサを Hpricot に変える

ずばり基本でしょう。

Mechanize は 0.9 以降デフォルトパーサを Hpricot から Nokogiri に切り替えているが、そもそも Nokogiri は HTML 用にできていない。XML 用の道具に、 Hpricot によく似たインターフェイスを付けたものである。HTML は自由度の高い書式で、XML 用のノコギリでは歯こぼれを起こすことがよくある。

そこでこの設定(0.9.0 〜 0.9.2)。

require 'hpricot'
WWW::Mechanize.html_parser = Hpricot

cf.

0.9.3 (以降?)はサブクラスの利用に注意

html_parser がインスタンスのアクセッサとして定義されたのでインスタンスごとに parser をセットできるようになったのはいいんだけど、Mechanizeクラスオブジェクトのインスタンス変数を self.class で参照して自身に書き戻しているので、

サブクラスに反映されない

状態になっている。(少なくとも Ruby 1.8.7 では parser が nil になって動かなかった。)定義部分は以下のような感じ。

class Mechanize
  ...
  @html_parser = Nokogiri::HTML
  class << self; attr_accessor :html_parser, :log end
  def initialize
    ...
    @html_parser = self.class.html_parser
  end
  ...
end

動かすとこんな感じ。

$ cat sub_mechanize.rb
class SubMechanize < WWW::Mechanize
end
$ irb
irb(main):001:0> require 'mechanize'
=> true
irb(main):002:0> a = WWW::Mechanize.new
=> (snip)irb(main):003:0> a.html_parser
=> Nokogiri::HTML
irb(main):004:0> require './sub_mechanize'
=> true
irb(main):005:0> b = SubMechanize.new
=> (snip)
irb(main):006:0> b.html_parser
=> nil

恐らく Mechanize のインスタンスについては html_parser のセット方法に互換性をとりつつインスタンスごとに設定できるようにしたかったためにこうなったんだろうけど、いつもデバッグしやすいように独自のサブクラスを噛ましていた*1ので、まったく parse できない現象にハマってしまった。仕方ないのでサブクラスの中で独自に定義することにした。

class SubMechanize < WWW::Mechanize
  def initialize
    super
    @html_parser = Hpricot
  end
end

こんなんでいいのかな。

cf. RubyのMechanizeの0.9.3が6月8日に出てたっぽい - きたももんががきたん。

Field を作る

これはまだ初級。

Form#add_field!( name, value )

無駄に JavaScript に分離したフォームの場合、必要な field が HTML 上に存在しないことがよくある。その値を無理矢理 form 上に反映するために使う。

FileUpload を作る

これに気づいたときにはけっこう嬉しかった。add_field! では Field は作れても FileUpload は作れないから。

どうやるかというと、Form オブジェクトに対して instance_eval を使う。

Form#enctype = 'multipart/form-data'
Form#instance_eval {
  @file_uploads << WWW::Mechanize::Form::FileUpload.new( name[, filename] )
}

もともと file_upload が存在しない form として解釈した場合は enctype が違うことがある(というか指定してないかも)ので手で変更してあげると吉。

Form を作る

instance_eval() を思い出してしまえば簡単。もう form そのものを解釈できませんでしたという凶悪な HTML 向け。

Page#instance_eval {
  @forms << WWW::Mechanize::Form.new( node[, mech, page] )
}

node には Hpricot::Elem オブジェクトを入れてあげれば ok.

このとき、Hpricot::Elem になれば元の文字列はなんでもよいので、

Form.new( Hpricot( String#scan( /<form.*?>.*?<\/form>/m ).to_s ).at( 'form' ) )

みたいなこともできる。HTML が壊れているので正規表現でいったん form だけ引っこ抜いて、それを Hpricot オブジェクトに戻してやって Form を作る。途中の整形も思いのまま。

Page を作る

Page を作るのはちょっと手が掛かる。以前作ったものを gist に置いてあるので参考になれば嬉しい。

*1 http://gist.github.com/76140