トップ 最新 追記

2007-09-01 [長年日記]

_ デスノートアニメ見た

リューク視点からなのが斬新、て別に本編はフツーに流れてて最初と最後に語りをくっつけただけでは…。ディレクターズカットってこの部分のこと? あとはテレビでやってたやつを編集し直しただけじゃないの? 通常のアニメのシリーズを見てないから知らないけど、終盤の L の描写の中に過去を連想される部分を変に入れてきたなという以外は普通に流れていったような気がする。

ただまぁさすがに3時間しかないとは言え端折りすぎだなぁ。説明として必要なシーンや血文字で殺すシーンがないし*1。あと最後 L に黒ライトの表情を見せなかったのはなんでだろう。さすがに救われなさ感が強くなりすぎるから? でも墓の前で黒ライトぶっ壊れてたしなぁ。そっちで入れるから重ねるとクドいという判断か。

しかしこうして見直すとやはり映画のラストのノートの使い方や南空ナオミの使い方はいかにも映画的だったんだなぁという気がするな。

*1 テレビシリーズを見ていないのでアニメに最初からなかったのかどうかは知らないけど、あそこは黒ライトが黒ライト自身を守るために必要な攻防なのだから。

_ PEAR_PackageFileManager_Cli で pear パッケージを作る

タイトルで全部なんですけど。

pear コマンドで管理可能なパッケージを作るためには

  • package(2).xml ファイルを作成して
  • pear package package(2).xml と入力

するとパッケージができるんだけど、この package(2).xml を作成するのが面倒らしく、いろいろフロントエンドがあるらしい。そんな中 PEAR_PackageProjector -lAiki に期待していたんだけど、試したら依存している CodeSniffer が PHP5 じゃないと動かないので使えないことが判明。(まぁその辺はイロイロあるでしょうがとりあえず無視。)

改めて調べると PEAR :: Package :: PEAR_PackageFileManager_Cli なんてのがあり、Pyrus - A few PEAR compatible packages を見ると順番に質問に答えるだけでよさそう。

2007-09-01 現在、0.3.0 alpha なのでインストール時は

pear install PEAR_PackageFileManager_Cli-alpha

としておく。

実際試した(OSX 10.3.9 PPC + PHP 4.4.4)ところ

  • pfm コマンドが作成されたので、パッケージを作成したいファイル群のてっぺんのディレクトリで pfm を起動
  • 順番に質問に答えていくだけ。ライセンスとかパッケージ名やバージョン以外は適当にデフォルトで進んじゃってオーケー
  • CVS とか .svn は自動的に避けて package.xml を作成してくれるので working copy 上で無造作に作業可能

など結構親切な印象。ちなみに聞かれる内容は pfm 0.3.0 で以下の通り

 1. Package name
 2. Channel/URI
 3. Summary
 4. Description
 5. Maintainers
 6. Version
 7. Stability
 8. License
 9. Notes
10. Dependencies
11. Tasks
12. Regenerate contents
13. Echo package file to stdout
14. Save & Quit
15. Quit without saving          (ctrl-c)

package名がモジュールの prefix になっていないと警告が出るなど、pear package としての作法を教えてくれるので、その辺を直しながら package としての体裁を整えていけばいいのかな。

課題

  • package2.xml を作る方法が分からない
    • package.xml という名前だけど中身は version 2 なので気にしなくていいかも
  • PHP_CompatInfo を使って利用できるバージョンを正確なものにしたかったが、CLI で動かしてみたらなんかエラーで動かなかった。なんだろ。
  • channel サーバもあった方がいいかなぁ
    • URL を直接指定させる方式なら channel サーバ要らないのかな
    • でも channel サーバあれば update とかのチェックしやすいよね

[追記] PHP_CompatInfo の問題は単に依存しているライブラリが足りないだけだった。これしかしなんでこんな table 形式で出力するんだ? 他のテキストツールで加工しにくいじゃん。

cf.

Tags: PHP PEAR

2007-09-02 [長年日記]

_ Perlベストプラクティスを買っちゃいそうな自分がいる

8月にやたら Amazon さんから荷物が届いたおかげで金銭感覚がマヒしつつある。勢いあまって 『Perl ベストプラクティス』もほしいなぁとか思い始めているから怖い。まぁ特に Perl は普段使わないようにしている分、自分の中の知識というかクセがかなり古くなっている自覚はあって、『救命病棟』も持ってるけど、これよりもっと細かいレベルでかつ具体的にこうすべしというノウハウに溢れるベストプラクティスに惹かれつつある。

ぶっちゃけ金銭的にキツイわけでもないし、持ってて損はしないとは思うんだけども、場所の確保がねぇ。(Perl メインのお仕事なら絶対買うけど。)あと Perl 関係の本て他にも『システム管理』とか魅力的な本がたくさんあるので歯止めが効かなくなりそうってのがいちばん恐ろしいポイントなのかも。

ということで、ここのところ毎日 Web 上の情報収集だけに留めようと必死に抵抗している。HACKS と違って自分用のメモがどうにか構築し終わればこの熱は冷めると信じている*1

*1 HACKS シリーズを全部自分のメモで代用するのは無理。


2007-09-03 [長年日記]

_ 隠すことによるセキュリティの向上は望めない、が原則では?

スラッシュドット ジャパン | サーバのバージョンは隠すのが常識?

これはー。

隠すことによるセキュリティの向上は望めないことを自覚したうえでやってね

という話に尽きる気がする。

こういったサーバ情報をわざわざ表示する必要はありません。

というのはその通りなんだけど、タイトルの「5分でできるセキュリティ向上」には役に立っていないことは触れなくていいんだろか。

さらに言うと個人的にはこの手の話は

  • バージョン情報を隠す/隠さない
  • 最新のバージョンを使う/使わない

以外に、

  • バージョンはそのままでパッチを当てる

という選択肢が存在していることがもっと広く知られてほしいという気がするかなぁ。意外にね「あー Apache のそのバージョンには脆弱性が云々…」てなことを「得意げに」言う人ほどその情報だけを鵜呑みにしてて、いや、パッチ当たってるんですけど、と軽く反論してみても全然聞いてなかったりするんですよね。そういうのって、本人は聞き流しちゃってるからなんともないでしょうけど、ハタから見てるとかなり恥ずかしいですよ。

あと .svn がどうたらというのはその前段階から対策取るのが本筋で、ステージングサーバから本番への反映の際にルールで弾けばいいような気がするんだけど、それじゃダメなのかな。rsync だろうが WinSCP だろうが exclude の設定はあるよ。そのうえでサーバ側で Deny するのはアリだと思うけど、Deny の設定はあくまでスタートに過ぎない気がする。.svn が誤って上がってる場合があるってことは *~ とかも上がってるよね、きっと。*~ は上がってなくても .1 とかは上がってるかもしんない。

/* 実際、昔引き継いだサーバはそんなんばっかだった。バージョン管理もしてないから .bak.old とか訳の分からないものだらけ。 */

その辺のプロセスを見直さないと、セキュリティの向上を謳うことはできないんじゃないかなぁ。

p.s. はてブコメントの「例えば PHP を使わない」に軽く吹いた。

_ Cperl-modeを使おうかどうしようか

気分転換に Cperl-mode で編集してみようと思ったらデフォルトの色の設定があんまり気持ち悪いのでビビってしまった。ソッコー perl-mode に戻す。

反転はさすがに使わないでくれ。

……。

あー。もしかしてコレ、変な色にならないように書いていればそれなりに行儀良く書けていると判断することもできるのか? んーなんか重たい感じがするなぁ。

[追記] M-x customize をあれこれ眺めてみた。色の設定はとりあえずいじってみたけど、perl-mode みたいに $ だけは色を変えないとか、コメントの中は全部赤とかにはできないのかな? 重さは Customize の中から細かく調整できそう。

あとは色に目が慣れればなんとかなるかもしんない。

Invalid Face っていう設定項目があるから、なんか他のツールと組み合わせるとおかしな部分をどぎつくハイライトさせて矯正、っていう使い方はできそうだな。やらないけど。

Tags: Emacs Perl

2007-09-04 [長年日記]

_ Cperl-mode 重すぎと思ったら Emacs の問題だったか?

試し始めた Cperl-mode だけど、Debian etch(4.0) の Emacs(emacs-snapshot) との組み合わせが悪いのか、なんかプロセッサパワーを食いつぶしちゃう。これはさすがにおかしいなぁということで使用を諦めることにしようかと思ったけど、Fink で入れた Emacs 22.1 (OSX PPC) 上で使う分にはたぶん大丈夫な感じなので、testing の 22.1 を入れたらいいのかもしんないな。もしかすっと。

と思って改めて見てみると backports に Emacs 22.1 が来てた。おぉ。ということで emacs-snapshot を apt-get remove して emacs22-nox をインストール。

……。

んー。まだ跳ね上がるときがあるなぁ。ずっと上がりっぱなしではなくなったけれども。メモリじゃなくてプロセッサパワーっつーところがいったい何しとんじゃいという感じ。こんなにクソ重ければそれなりに話題になっていそうなもんなのに、そういう話は見ないもんなぁ。

Tags: Emacs Perl

2007-09-05 [長年日記]

_ Mac 使っててもフツーの人にはキモがられるのがオチです、きっと

Rubyist Magazine - Rubyist Hotlinks 【第 19 回】 伊尾木将之さん

いいなぁ。このモテるかも、モテそうっていうのを Ruby 界隈で声高に言う人ってあんまり見ない気がするな。JavaScript とか CSS とか PHP とか Zope とか(え)なんかそっち方面のような気がする。

でまぁ、タイトルの通りですけど、Mac 使っててモテる可能性があるのって、例えば雑貨屋とかああいう、Mac そのものが似合う空間に居て違和感のない人なんじゃないかと思いますよ。つかほら Mac ってフツーに宗教入ってますから。

話飛びますがトラベルキーボードを Mac に繋いでゴニョゴニョすれば使えます*1。ただ Windows キーがないんで、option キーをどこに割り当てようか悩みますけど。CapsLock を Ctrl にして、Ctrl を option キーにする、CapsLock はナシっていうのも潔くていいけど。

……。

はて。

なんでるびまなんか読んでたんだっけか。Perl 読んだり書いたりするのがイヤになっただけだったか? 違うなぁ。なーんか調べようと思ったんじゃなかったかなぁ。Rubyの会の Wiki の編集してる場合でもないはずだよなぁ。

なんだったかなぁ。

*1 軽すぎて常用するにはアレですけど、滑り止めとか重りとかつければいいかも。

_ 思い出した ICU だ。

ときどきの雑記帖 リターンズ 2007年9月(上旬) - PHP

PHP 6 が ICU 拡張を採用とか言う辺りで ICU ってなんだんねん。あ、Ruby の方式か?(それは CSI)と思ったのがきっかけでるびま読んでたんだった。

ICU は昔は IBM Classes for Unicode と呼ばれていたらしいが、今は International Components for Unicode ということになっているようだ。

cf. ICU Homepage @ icu-project.org

Unicode っていっぱいあるなぁ…。

Tags: Text PHP Ruby

2007-09-06 [長年日記]

_ Perlリハビリまとめ

最近のリハビリで、だいぶモダンな書き方ができるようになったような気がする。結局今回いじった箇所は全書き換えはしてないんでそんなに新しくなってないんだけど、テストを含めて割と新しい使い方ができるようになった雰囲気。

Perl は後付け後付けで機能を拡張しているうえに古い情報が蔓延していることもあって、きちんと整理された新しい書き方を修得するのにそれなりに時間も掛かるが、古いスクリプトをそのまま動かすこともでき、ちゃんと書き直せば新しい機能の恩恵にも与れるという懐の深さはやはり非常にありがたい。今回初めて Perl 5.8 ならではの機能も試したが、これが出たのがもう5年前ですよ。どうよこの枯れっぷり。PHP に爪のあかを飲ましてやりたい。*1

ただ、

  • 標準じゃないモジュールを探しまわるとか
  • リファレンスリファレンスリファレンス

うぜえよ。

CPAN モジュールは多過ぎるしうっかり手を出すと依存関係が面倒くさいし。まぁその辺含めてこうしろと言ってくれる、放任しない教師としてベストプラクティスはみんなにオススメなのかもしれないんだけど。

最後にまとめると、「書き直す機会があればやはり Ruby にしたいという気持ちが強くなった」のは間違いないっす。以前よりは Perl きらいじゃなくなったけどね。それがいちばんの収穫かなぁ。Golf系でない方法でコードを短くしていけばまだそれなりに耐えられるし。多少記法が違ってもコードそのものの見通しのよさには関係ないっつーことか*2

[追記] あ。まだ調べてないのがあった。その辺りは、

  • 日付処理は Class::Date
  • 例外処理は Error

にしてみた。

DateTime は確かに便利なんだけど上で書いた依存性地獄に近いので却下。Fink にも deb にもパッケージがあるから扱いは楽だけど、そうでない環境に行ったときを考えると恐ろしい。Class::Date は pure Perl で小さすぎず大きすぎないところがよい。日付計算もできるのであれこれ道具を持ち替える必要がない。時刻の扱いは弱いけど、そのときは時刻だけにフォーカスしたものをまた探せばいいかな。そんなに必要ないと思うけど。ISO 8601 フォーマットって初めて知った。

例外は書き方が Error の方が分かりやすかったのでとりあえず選んでおく*3。例外オブジェクトそのものの定義は Exception::Class が書きやすいかもしんないけど、eval して catch してっつーのはちょっと Perl 的すぎる感じがいやだ。Error.pm なら try {} catch with {} finally {} など分かりやすい。

例外オブジェクトはとりあえず Error::Simple を継承した適当なオブジェクトを作っておけばいいんじゃないのかしらんと踏んでいる。この辺、独自の知識やノウハウが必要ないのも Error.pm の方がよさげと判断するところ。ただ継承は Ruby なら class < だけで済むのに Perl だと package ; use base になってしまうというところが邪魔くさいんだけど 。もうそこはしゃあないか。ちっ。

以下は Perl 関連のエントリを並べ直してみたもの。

あと今まで書いたり書かなかったりしてたほんとに細かいけどフツーに使うのは、

  • use lib (@INC をいじる代わり)
  • use base (@ISA をいじる代わり)

これしかし逆に言うと lib とか base とかモジュールの名前としておいしい名前を使えなくなってしまっているのよね。

  • File::Basename
  • File::Spec
  • Cwd qw( realpath )

は必須。strict と warnings も必須。

本格的な Web アプリには使ってないのでその辺は知らない。テンプレートは HTML 目的で書き始めたけど、HTML 以外にも使ってます。

今度こそ最後。テストは個人的には Test::Unit::Case と Test::Unit::Runner を使う。Test::Harness 系というか Test::Simple 系というか、まぁ Test::Base なんだけど、あまりに Perl っぽすぎて独自すぎていやなので。

Tags: Perl

*1 というか Perl 5 らしい使い方にようやく追いついたのが実情なんだけど、Perl 5 が出たのはすでに10年以上前という…

*2 書きやすさは違うけど。モダンな書き方を目指すなら Perl より Ruby の方が短くしやすいし書きやすいと思う。

*3 散々ベストプラクティスを持ち上げといて実際自分はその通りにしないあまのじゃくっぷり。


2007-09-07 [長年日記]

_ Emacs の M-x grep をマルチエンコーディングに

なんかたまにエンコーディングの混ざっているファイル群に対して検索を掛ける必要があったりするんだけど、そのときだけ mi を起動したりしてものすごい敗北感を味わっていたんだけど、lgrep を使うことにした。

厳密には以前から emacs の grep で lgrep は使っていたんだけど、recursive に検索してくれなくてなんじゃこれめんどくさ、と放置気味だったわけ。

今回一念発起してこうしてみた。

(setq grep-program "find . -type f -a -print0 | xargs -0 lgrep -nk -Ou8 ")
  • UTF-8 出力で
  • 半角カナを全角カナに変換してから検索する

ようにしてみた。うむ、やっと便利になった。バイナリファイルも大量にあるっつー場合は適当に find の条件を書き換えて使うこと。lgrep を知らない人は勝手にググること。

Tags: Emacs

_ バージョン番号…

なんか今になってものすごく初歩的なことなんだけど、Perl で

print $];

はちゃんとバージョン番号を返すのに

use English;
print $PERL_VERSION;

は何も出ないな…。まぁ困らないっちゃ困らないんだけど、どうなってんだろ、これ。

Tags: Perl
本日のツッコミ(全2件) [ツッコミを入れる]

_ きむら(K) [$PERL_VERSIONは$] と違って、version stringのモヨリ。 printf "%vd", $P..]

_ wtnabe [ははぁ〜。なんかめんどくさいっすね、これ。てことは sprintf "%vd", $PERL_VERSION が R..]


2007-09-08 [長年日記]

_ PHP 5.2.1 以降は pecl で Syck か

PECL :: Package :: syck

ただなぁ。時代は PyYAML だっつってんのに今ごろ Syck なのかよという気はするんだけど。この辺、PHP 界隈はどうにも弱い印象だなぁ。

もっとも速さに関しては、そもそもはっきり差が出るようなでかい YAML を毎回パースさせるっつーのがおかしいので、気になるなら serialize(), unserialize() を使ってキャッシュすりゃいいんじゃないかとは思っている。あんまり真面目に計測したことはないけど、parse_ini_file() でまかなえない構造のものを扱いたくて速度もそれなりに気になりますって場合はそれが今のところベストじゃないかしらん。設定ファイルなんてそんな毎回書き換えるもんじゃないんだから。

まぁ YAML ファイルそのものをストレージとして使いたいとか JSON みたいにレスポンスとして使いたいとかいうんだったら話は別なんだろうけど。

Tags: YAML PHP

2007-09-09 [長年日記]

_ iPod Touch の面白そうなところ

どうしてもインターフェイスの方に意識がいっちゃうし、日本語がなぁとか思っていたら街角仕様らしいし、おぉ忘れてた、やはり実機試してみたいぜと思っているところなのだけれど、これ、単独で Safari と iTunes が使えるってのはやはり大きいんじゃなかろうか。

以下は iTunes が iTunes Store にしか繋がらない場合はかなり外れちゃう妄想。

iPod って基本的に外部のデバイスで楽曲データを生成してそれを取り込む形になっているので、ケータイばっかいじっていたい人らにはちょっと面倒なわけですよ。まぁ他のプレイヤーもそうだと思うけど、パソコンか、 rip と転送の機能を持ったラジカセみたいな何か、ステレオシステムっつーんですかミニコンポっつーんですか、なんかそんなやつを持ってなきゃいけないし、何より家に帰って作業しなくちゃいけない。ケータイだったら着ウタでどこでも一発なわけですよ。ケータイ大好きっ子には面倒くさくないですかこれ。

そしてもう一つ、ケータイ文化の人たちは基本的に PC でしか利用できない iTunes Store って使ってないですよね。つまり特に日本の若年層にはあんまり iTunes Store って届いてないんじゃないかと。それが iPod 一つで繋がるんだったら結構使われるようになるんじゃないかなぁという辺り。もっとも無線でしか繋がらないから家に無線 LAN ないとダメじゃん、と田舎ものは思うわけですけどね。ホットスポットなんてそんなにないし。まーでも若者の行動範囲のお店なんかがそういうところを敏感にキャッチして iPod Touch 使えますゾーンを整備していったら(TSUTAYA とかはすでに DS 向けにそういうのあるかもしんないし)、商売的になかなか面白いんじゃないのかな。(スタバ縛りなんてないよね?)

そんでもって iTunes と iTunes Store が日本のケータイ文化の人たちの間にも浸透していったら、インディーズとかはその辺にチャンスが生まれないだろうか。CD みたいにプレスして店頭に並べる方式だと在庫と流通の問題が必ずつきまとうけど、データだったらその辺はかなり扱いが楽になる。iTunes Store に入らなくても、PodCast として流通させちゃえばクォリティとか DRM とかはともかく聴いてくれる人は増える。そして、PC を持っていない人にもリーチできる。モニタ小さいからビデオ作家とかには厳しいかもしんないけど、今みんな喜んであんな小さいモニタでワンセグ見てるわけだから、案外成り立つかもしんない。YouTube だって冷静に考えると結構汚いしね。

まぁ課題はたくさんあって、

  • iPod Touch 内蔵の iTunes は iTunes Store 以外に接続できるのか?(Safari 積んでるんだしできると思うけど。YouTube と iTunes Store しか繋がらないんじゃ全然面白くないよね。)
  • Podcast とか Safari で探してきても DnD で iTunes に突っ込む操作はやりにくいよな
  • クレジット以外の決済をもうちょっと簡単にできないものか?(クレジット以外にもカードとかギフトとかあるけど、あれ文字だけじゃ分かりにくいよねぇ。)

あと

  • そもそも Apple はその辺どう考えてんのか

がいちばんの問題か。iTunes Store 以外に繋がっても Apple はそんなに嬉しくないよなぁ。

あ。

つーか完全に忘れてたけど、iPod Touch が Safari 積んでるってことはですよ。Safari を単なるマイナーブラウザと片付けられなくなるってことじゃないすか? NetFront, Openwave, Opera と来て Safari もちっこいデバイスのブラウザとして視野に入れなきゃダメになったってことだよね? これって Safari 3 ?

Tags: Apple Music Web

2007-09-10 [長年日記]

_ IEのドメイン当たりクッキー数の上限が20から50に増えるらしい

Internet Explorer で、ドメインあたりの Cookie の数の制限が 20 から 50 に増加する

RFC 的には user agent は最低 20 扱えるようにしろ、と書かれているだけで上限はないっぽい?

RFC 2965 HTTP State Management Mechanism

によると、

Applications should use as few and as small cookies as possible, and they should cope gracefully with the loss of a cookie.

ではあるけれども、

忍者 TOOLS の悪行 - にぽたん研究所

で挙げられている Client Side State - HTTP Cookies に書かれている

Servers should not expect clients to be able to exceed these limits.

という記述を見つけることができないなぁ。なんか見落としてますか?

※ いずれにせよ最小限で済ませましょうよというのは間違いないんだけど。

Tags: IE Web

_ もやもやしたものがありますねぇ

そもそも MacOSX のファイル名は UTF-8 で取れるけど UTF-16 で保存されてるんじゃないのかとか思ったりもしますが、ウノウさんには番長名乗ってるテスタも居るわけで、スルーしちゃってるってことはですよ、これは要するにテスト項目として MacOSX のファイル名問題が全然上がっていなかったということを意味しませんか。ちょっとそれはどうなんだろう。

フォト蔵使ってないんで分からないんですけど、Mac での動作を保証しないアップローダというかファイル転送サービスは多いですよ。1ユーザーとしては諦めがついてるんで気にしてないですが。

まぁ今回も保証外ですで済まそうと思えば済ませる問題をそうしなかったという点は評価できるんですけどね。

Tags: OSX Web

2007-09-11 [長年日記]

_ svndumpfilter は意外と使えない

というのも、svn copy を利用してあちこちの branch で作業したファイルはその branch も include しておかないと途中で svndumpfilter が不正なパスとか文句言って止まっちゃう。こういうファイルが大量にあると include の引数がとんでもないことになってしまう。

結果、構成によるんだろうけど、手元のものは filter 掛ける前とほとんど変わらない状態にしかならなかった。容量で言うと1割ちょいしか減らない。欲しいのはもっとずっと一部なんだけど。うーん。リポジトリの分割って難しいな。svndumpfilter に force オプションとかあればいいのに。それか手作業? それとも revision を細かく指定しながら incremental に dump して cat?

うーん。

試しに dump ファイルを自前でパースして必要な Node-path の含まれる Revision-number だけ吐き出すスクリプトを書いてみた。この結果出力された revision だけを次々 dump していって、新しいリポジトリに load したら目的のものができるだろうか?

まだ実験は続く。

#! /usr/bin/env ruby

rev = 0

while ( line = gets )
  line.chomp!
  if ( line =~ /\ARevision-number: ([0-9]+)\z/ )
    rev = $1
  end

  if ( line =~ /\ANode-path: (.*)\z/ )
    if ( $1 =~ RE )
      puts rev
    end
  end
end

実際に使ったものとちょっと違うので試してないけど、必要なところを直せばたぶん動きます。あれこれめっちゃ決め打ちです。出て来た数字の羅列を uniq してください。たぶんこんな感じ。

ruby SCRIPT dump-file | uniq > DEST

uniq 持ってない人は while の中で rev を配列にツッコんで最後に

puts array.uniq.join( "\n" )

してください。(最初そうやろうとしたけど、瞬時に動作の様子が見れなくてむかついたのでやめたのでした。)

[追記] 厳しい。

必要な revision だけを dump しても結局 revision の完全な状態を再現可能な dump を作成するので意味がない。--incremental を付ければその前の revision からの差分で dump してくれるが、revision 減らそうって言ってるんだからこいつらを load しまくっても正しくリポジトリを復元できない。

可能な対応は、フル dump に対して、関係する path が含まれていない revision あるいは node を削除していく、というスクリプトを作ることか? でもそうすると dump ファイルを自前でちゃんとパースできないといかんな。(上に挙げたものはかなり適当。)それとも完全自動化は諦めるか? うーん、それもつらい。できなくはないと思うけど。基本的には

Revision-number:
Node-path:
Node-path:
..
Revision-number:
..

こういう構成なので、除外したい Node-path や Revision-number を切っていくのは順番になめていくだけで可能。

つーところまで分かったところで、他にやることがあるのでこれは後回し。誰か作ってくれないかしら。

でもなんか新しいリポジトリでは昔の歴史は思い切って捨てるという判断がいちばん正しいような気がしてきた。負けですか?

※ 最終的には手作業での dump ファイル修正を含めて目的の形にリポジトリを分割することができました。

cf.


2007-09-12 [長年日記]

_ そりゃLL使いでも低レベルを知っているに越したことはないに決まっている

えーと、最近の一連の話はほとんど読んでませんが、C もアセンブラもかじった程度にだけ経験はあるけど BINARY HACKS はほとんど分からなかった*1 LL な人間として思うことは

絶対に知っとけとは言わないけど、知ってると勘は働くよ

ってことかなぁ。勘て書くと誤解を生みそうだけど。

C やマシン語をきちんとやらなきゃいけないって意味じゃーないんだけど、低レベルの動作がある程度想像できるようになっていると、例えばあまりに非効率な方法は実際に書いて動かしてみる前におかしいと気づきます。(なんつーか、これを詳細設計と呼ぶのかもしれない。知らんけど。)

例えば DB からデータを取得するときに、まるでテキストファイルを相手にするかのごとくシーケンシャルに一つずつ取ってくる*2とか、テキストファイルからデータを取得する際に OS のバッファリングなどに丸投げせずに自分で妙な技を開発しちゃうとか、そういうのはフツーあり得ないわけですけど、何がどうあり得ないのかきちんとマシン語レベルで説明できなくても、そりゃ効率悪いに決まってるやんとかは気づくわけです。なんとなくですけど。*3

同じように、アルゴリズムとデータ構造といった、いわゆるコンピュータサイエンスの基礎中の基礎に当たる部分もやっておくと、この場合にこんなデータ構造にするわけないじゃんとか、これは有名な○○のアルゴリズムをそのまま当てはめればいいし、それは標準関数のこれこれとかライブラリのどれそれですぐに実現できちゃうのに、なんでそんな力技を編み出そうとするの?とかいうのも、実際に書いて動かす前に気づけるわけです。*4

そういう意味での基礎体力というか、そんな感じで役に立ちます。もちろんそういう効率の悪いコードを書いてしまっても、それをきちんと計測して遅いから別な方法を採用した方がいいなと判断できる力があるならそれでも構わないとは思うんですが、残念ながらそんな、いい意味でアンバランスな人*5にはお目にかかったことがありませんし、書く前に気づけるならそれに越したことはないわけです。なまじっか動くものができちゃうとそれを壊したり直したりするのに抵抗が生まれたり*6するでしょ? 動くものができる前なら遠慮なく破棄できますから。

LL や Java など VM 上で動く言語を使う人間としてはそんなの知ったことかと思いたいわけですよ。そんなのお前らがいい具合に勝手に解釈しろと。まぁそこまで乱暴なことは言わないまでも、「コンピュータなんだからそれくらい良きに計らってよ」に近いことをぼんやりとですが、考えていたりするわけです。よく考えると「開発者」とか「技術者」を名乗るにはあり得ない発想だったりしますけど*7、まぁやっぱ基本的にプログラマは楽をしたいから苦労する人間なわけで、楽をしたいと思うこと自体は否定しちゃダメなのかなとも思います。

話がそれた。

とにかく、あんまりこと細かに具体的な話をするのは難しいんですが、知ってるに越したことはないよというのは間違いないです。そしてこれは特定の言語のクセとして慣れるのとは違うレベルでの力なので、言語を乗り換えても活きます。例えば「PHP のプログラムを高速化するための 10 の Tips」みたいなのってものすごく人気あるわけですけど、そういう知識は PHP を使わなくなったら役に立たなくなります。でも低レベルの知識は PHP だろうが Ruby だろうが役に立ちます。低レベルがガラッと変わっちゃうことはそうそうないですから。

ただまぁ、くり返しになりますが、優先順位はそんなに高くないと思います。

  • プロファイラがちゃんと使える
  • 論理演算というか集合がちゃんと分かる
  • テストをちゃんと書く
  • 黙ったまま作業しないでちゃんと commit する
  • 構成管理のツール(Trac とか)が入ってるならちゃんとそれを使う

とか、「上のレベル」で身につけなきゃいけないことが多いですし、少なくともここに挙げたものを満たさずにマシン語レベルの話が分かったからと言って大きな顔をするようなやつは廊下に立ってろですよ。*8

最後にこれものすごく疑問なのですが、例えば Perl のリファレンスとか Lisp の car, cdr なんかを、メモリアドレスとか C のポインタとかを知らずにどうやって理解するんでしょうか? そこら辺がどーも私にはピンときません。Perl ハッカーで C もアセンブラもさっぱりですという方がいたらご一報ください。お友達になりましょう。

cf.

*1 というかネタとして買った

*2 単にロックの仕方をちゃんと知らなくても安心して使えるストレージに成り下がっちゃってる

*3 例えば一回 C でファイルの読み書きを全部書いてみりゃどれだけコストがでかいかは実感できます。少なくともまともに動く C のソースを書き上げるだけで面倒です。Ruby なら File.open( moge ) { |f| } で一発なのに、とか思いながら書くのでますますうっとぉしいです。

*4 と、言いつつ自分はあんまりそういうのが役に立つようなことはしてないですし、どれだけの精度で自分に当てはまっているかについては自信はありません。ありませんけど、世の中にはそういうの全然分かってないのに自信満々な自称プロの方もいたりして、不思議だなーと思うことはあります。

*5 低レベルの知識ゼロなのにプロファイラ使いこなしてる人

*6 自分の心の抵抗じゃなくて外圧の場合もある

*7 それを実現するのが己らの仕事じゃねーのかよ

*8 くどいようだけど、これは低レベルの知識がなくても書ける LL を前提にした話ね。


2007-09-13 [長年日記]

_ svnadmin dump した結果を覗く

※ 手元の zsh を 4.1.1 から 4.2.5 にしたら突然便利になった。今まで ssh の hostname も補完してくれないし、なんか不便だなーくらいに思いながら使っていたのだけれど、これはなんかすごいかもしんない。そして 4.3.2 の環境の zsh は compinit してなかったよ! バカですか、おれ。補完が強力になるとなんかこう、羽が生えたかのように軽やかな気持ちになりますな。

えー。

先日の svndumpfilter の続き。要するにリポジトリの中から要らないリビジョンを消しちゃえばいいんだろと思ったんだけど、無関係な node だけを削除するのではダメことが分かった。

それは cvs2svn がブランチを切る際に、丸ごと trunk を branches 以下にガバっと copy したあとに不要な node を削除しまくるという作業を一つの revision でやっているため、Node-path だけ見てても必要かどうかを判断できない。Node-path だけ見て拾ったものがいきなり delete アクションに割り当てられててなんじゃこれと思ったら直前に copy されているというわけ。ということはこの copy のアクションが残ってないと dump ファイルを load したときにエラーが出ちゃう。

本当に無関係なら copy も含めて revision まるごと削除すればいいんだけど、その本当に無関係かどうかを機械的に判断するのは結構難しい。例えば必要なパスの中のさらに一部のファイルにだけブランチタグを打っていた場合、cvs2svn では丸ごと copy したあと、その必要なファイル以外を次々 delete していくという履歴を起こしてくれるんだけど、この履歴を見ただけじゃ残るファイルがなんなのか分からない。それこそ svn と同じことをして前から順番にたどってこないとこの時点でそのファイルが必要かどうか分からないのだ。うーん。なんだこれ。履歴を辿りながらすべての Node-path を記録していって、この時点の丸ごと copy ではこれだけのファイルが対象になるってことを確認しないといけない。

って、それまんま svn の仕事やんけ。

Subversion に移行したとき、要るファイルだけを別 branch に copy するのがものすごくやりにくいと思った記憶はあるんだけど、まさかそれがこんな形で効いてくるとは。丸ごとコピーして削除ってそりゃないよ!

copy のアクションがあったらその revision はとりあえず残す方針にして、そのあとの delete アクションで確実に自分の意図したパスが除外されていると分かる場合だけその revision を削除できる…。もっと簡単なパターンマッチで処理できるかと思っていた。甘かった。

※ 最終的には手作業での dump ファイル修正を含めて目的の形にリポジトリを分割することができました。

cf.

Tags: Subversion

2007-09-14 [長年日記]

_ dump file の手作業での修正を試みる

とりあえず必要なパスが含まれている node とそれを含む revision、copy してる revision をスクリプトで抜き出して、全部で 700 ちょい。これを load しながらどうしてもエラーの出るところに関しては手作業で dump ファイルを修正してみている。

エラーが起きるのは基本的に svn copy を実行する、ブランチタグを切る revision がほとんどなので、そんなにむちゃくちゃな数にはならない。あとは必要なパスの上の階層がすでに add されていないといけないので、その分も加えてやる。

これを全部自動化できればベストだが、とりあえず方法として間違っていないかどうかの確認を兼ねて実験。

結果、dump ファイルのパースをする際に無造作に改行コードを chomp したのがいけなかったのか、途中でデータに矛盾が出てきた。そこまででできあがったリポジトリを見る限り、そこまではうまく抜き出せていそうなので、あとはその辺をクリアできるかどうかだけかな?

改行コード周りかなーと踏んでいるのは、Subversion は内部の改行コードを LF に統一しているとマニュアルに書いてあるのに CRLF がそのまま入ってる箇所があったため。これはたぶん何らかの不具合の結果なんだと思うけど、実際に CRLF になってしまっているため、Ruby で chomp( "\n" ) すると \r\n が削れてしまい、出力時に \n しか付加しなかった場合は変換後のデータがオリジナルのデータと食い違ってしまう。結果、Content-length も md5 も合わない。

続きは休み明け。とりあえず狙った形のリポジトリには近づいている。

※ 最終的には手作業での dump ファイル修正を含めて目的の形にリポジトリを分割することができました。

cf.

Tags: Subversion

2007-09-15 [長年日記]

_ 長野1日目

妻籠宿

木曽路はすべて山の中にある。

いやー。

つか木曽路どころじゃなくてみんな山の中だもの。

※ 写真がドアンダーなのは明かりを引き立てる演出と手ぶれ対策を兼ねてます(こすい)

Tags: Photo 日々

2007-09-16 [長年日記]

_ 長野2日目

飯田市街地からの雲海

今回の道中いちばん感動したのは普通に市街地の真ん中で雲海を見れる飯田市。なんじゃそれと。

イマイチ眺めがよくないのは赤信号の間に運転席から撮ったから。止まってゆっくり撮るのは機材のアラが目立つので却下。こういう記念写真は感動の瞬間を切り取れるか否かの方が重要なのです。

暗めなのは雲だけに目がいくようにアンダーで撮ったうえでハイライトだけ起こしてやってるからです。

で、ここから向かったのが天竜峡。

天竜峡

ここだけ唯一雨に祟られ、天竜川下りを断念した。よく見ると分かるかもしれないけど、雨が降ったら船の上にビニールで屋根するのね。そんな情緒も景観も台無しな川下りしてもねぇ。

3日目は体調崩してたのと、なんと善光寺が来年再建300年でガッツリ工事中だったので使える写真ないです。

なんかどうもね。

観光地で工事に当たるな。

Tags: Photo 日々

2007-09-18 [長年日記]

_ zsh やっぱ戻した

そういえばこの Fink の 4.2.5 は日本語ディレクトリに cd しようとすると落ちるんだった。忘れてた。それで使ってなかったんだ。しくしくしく…。

Tags: Zsh

_ 手作業修正 -> load 完了

svnadmin dump した結果をスクリプトと手作業で編集して svnadmin load するのに成功した。まぁ成功して当たり前なんだけど、一応メモ。使ったのは svn 1.4.2 と Ruby 1.8.5 とエディタ。

svndumpfilter はそんなに使えない

svnadmin dump の結果に対して path で単純なフィルタリングを行う svndumpfilter というものがあるが、これを適用しても特に以下のようなリポジトリレイアウトの場合、あまり役に立たない。

branches/
  各モジュール/
  ...
tags/
  ...
trunk/
  ...

このツールは以下のようなレイアウトになっていて、

モジュール/
  branches/
  tags/
  trunk/
モジュール/
  branches/
  ...
...

ここで言うモジュール単位に分割する際には使える。つまり、リポジトリそのものの操作がのちのち楽なのは後者のレイアウト。

新規にリポジトリを作成する場合はともかく、cvs2svn で既存のリポジトリを変換する場合は何も考えないと前者のレイアウトになってしまうので注意が必要。

※ その他にも cvs2svn は svn:eol-style を native にしてしまうのでクライアントのプラットフォームが混ざっている場合に思わぬ不具合を引き起こす可能性がある。

dump したテキストファイルは mbox のような感じ

なので、mbox っぽいデータを自分でパースしたことのある人ならなんとかなります。XML ではないのでデータの終わりは明示されず、始まりしか明示されないので、始まりの区切りをそこまでのデータの終わりとして機能させれば ok.

ただし改行コードは混ざっているので注意。パースする際に改行コードを無造作に chop しちゃダメ。

タグを打った操作の追跡時に注意が必要

svn copy は特定のパスだけを copy する作業がなかなかやりにくい。これが cvs2svn を使ってリポジトリを変換した際、タグを打つ操作に対応する revision を見るとなるほどと思う。丸ごといちばん上の階層から copy して、不要なパスを delete している。このとき、この delete するパスが存在していないと load の際に失敗する。

つまり、

branches/
  ..
trunk/
  path1/
  path2/
tags/
  ..

というリポジトリがあり、

branches/
  path1/
trunk/
  path1/

のように path1 だけを取り出したいという場合、最初の方の revision で path2 を add する作業をカットしてあると、copy -> delete のコンボ revision の中で path2 を delete するアクションがあってはいけない。

でもまぁ手作業対応もそれなりに可能

今回はまだリポジトリの full dump が 124MB、取り出したい部分の dump ファイルが 26MB で収まっていたので、なんとかエディタで開いてスクリプトで対処しきれなかった余計な部分のカット、逆にスクリプトで取り除きすぎてしまった部分を full dump から戻す作業を行えた。(重かったけど。)ブランチの数もせいぜい数十。

ただこのレベルを越えるとなるともっと精度の高いフィルタが必要だなとは思った。

使ったスクリプト

本当はできるだけ手作業を減らそうと、revision ごとに dump ファイルを分割する機能をつけて、保全した revision の差分を取ってゴニョゴニョ(まだあまり考えていない)する機能をつけようと思っていたのですが、面倒くさくなったので放置です。

実に中途半端な状態ですが、とりあえずバックアップ目的で貼っておきます。なんか使えそうならご自由に。

#! /usr/bin/env ruby

require 'pathname'
require 'logger'

=begin

Subversion の dump ファイルから特定の条件を満たす node および revision
だけの dump ファイルを生成する。

Usage: ruby SCRIPT srcdump > destdump

Revision について
=================

Prop-content-length: は当然ヘッダ部以降 PROPS-END までのサイズ。

Content-length: は Prop-content-length と同じ。この数字は Node の
content-length に影響されない。つまり、Revision の途中で Node がバッサ
リ落ちても影響ない

ただし Node をただ単独で落とすと cvs2svn が作る、丸ごと copy してから要
らないものを削除するという revision に対応できないことがある。

Node-copy* という文字列を見つけたら Revision 丸ごと保存したい。

Node について
=============

Prop-content-length: はヘッダ部以降 PROPS-END までのデータのサイズ
Text-content-length: は PROPS-END 以降次のヘッダまでのデータのサイズ
Content-length: は上の content-length の合計

=end

#
# svnadmin dump した結果を処理するツール
#
module Svndump
  #
  # パースした node および revision に対する共通メソッド
  #
  class Common
    def initialize( loglevel = nil )
      _init_logger( loglevel )

      @curr_rev   = nil
      @curr_node  = nil
      @buf        = []
      @revs       = []
    end

    #
    # Logger の初期化
    #
    def _init_logger( level = nil )
      if ( level.nil? )
        return false
      end

      @logger = Logger.new( STDERR )
      case level
      when 'debug'
        @logger.level = Logger::DEBUG
      when 'info'
        @logger.level = Logger::INFO
      when 'warn'
        @logger.level = Logger::WARN
      when 'error'
        @logger.level = Logger::ERROR
      else # include 'fatal'
        @logger.level = Logger::FATAL
      end

      return true
    end
    private :_init_logger

    #
    # 指定ファイルまたは標準入力から dump ファイルを読み込みあれこれ
    #
    # 行ごとに分割して特徴的なヘッダ行をもとに pre_hook, post_hook を定義
    # chomp() しない。改行コードが混ざっている可能性があるので。
    #
    def read
      while ( line = gets )
        case line
        when /\ARevision-number: ([0-9]+)/
          revision_pre_hook()
          @curr_rev  = $1.to_i
          @curr_node = nil
          revision_post_hook()
        when /\ANode-path: (.*)/
          node_pre_hook()
          @curr_node = $1
          node_post_hook()
        when /\ANode-copy/
          nodecopy_pre_hook()
        end
        @buf.push( line )
      end
    end # of read()

    def revision_pre_hook
    end

    def revision_post_hook
    end

    def node_pre_hook
    end

    def node_post_hook
    end

    def nodecopy_pre_hook
    end

    def clear_rev_buf
      @rev_buf  = []
      @keep_rev = false
    end
    private :clear_rev_buf

    def clear_buf
      @buf      = []
      @storable = true
    end
    private :clear_buf
  end # of class Common

  #
  # dump ファイルを各 revision ごとに分割する
  #
  class Splitter < Common
  end

  #
  # 小さくする
  #
  class Compact < Common
    #
    # コンストラクタ
    #
    def initialize( loglevel = nil )
      super( loglevel )

      @dump_header = true
      @keep_rev    = false
      @rev_buf     = []

      @storable    = true
    end

    #
    # 主処理
    #
    def run
      read()
      after_all()
    end

    #
    # Revision-number の切り替わりのタイミングで呼ばれるメソッド
    #
    def revision_pre_hook
      if ( !@logger.nil? )
        @logger.debug( "in revision_pre_hook() rev #{@curr_rev} node #{@curr_node}" )
      end
      store2rev()
      output_rev()
      if ( @curr_rev == 0 )
        @dump_header = nil
      end
    end

    #
    # Revision-number の行を読んだ瞬間に働く hook
    #
    def revision_post_hook
    end

    #
    # Node-path の切り替わりのタイミングで呼ばれるメソッド
    #
    def node_pre_hook
      if ( !@logger.nil? )
        @logger.debug( "in node_pre_hook() rev #{@curr_rev} node #{@curr_node}" )
      end
      store2rev()
    end

    #
    # Node-path の行を読んだ瞬間に働く hook
    #
    def node_post_hook
    end

    #
    # Node-copy* 行が現れるタイミングで呼ばれるメソッド
    #
    def nodecopy_pre_hook
      @keep_rev = true
    end

    #
    # 全部読み終わった時点で呼ばれるメソッド
    #
    def after_all
      if ( !@logger.nil? )
        @logger.debug( "in after_all() rev #{@curr_rev} node #{@curr_node}" )
      end
      store2rev()
      output_rev()
    end

    #
    # 現在の @buf の内容を保存するかどうか
    #
    def store?
      return ( @keep_rev or @storable )
    end
    private :store?

    #
    # dump header および revision 0 かどうか
    #
    def dump_header?
      return @dump_header
    end
    private :dump_header?

    #
    # @buf_rev の内容を出力する
    #
    # 出力後、クリアもする
    #
    def output_rev
      if ( !@logger.nil? )
        p @curr_rev
        pp @rev_buf
        p "dump_header #{dump_header?}"
        p @rev_buf.size
      end
      if ( dump_header? or @rev_buf.size > 1 )
        @rev_buf.each { |buf|
          puts buf.join()
        }
        @revs.push( @curr_rev )
      end
      clear_rev_buf()
    end

    #
    # @buf の内容を @buf_rev に store
    #
    def store2rev
      if ( !@logger.nil? )
        @logger.debug( "in store2rev() store? #{store?}" )
      end
      if ( store? and @buf.size > 0 )
        @rev_buf.push( @buf )
      end
      clear_buf()
    end

  end # of class Compact
end # of Svndump

#
# テストじゃなかったら実行する
#
if ( Pathname( __FILE__ ).realpath == Pathname( $0 ).realpath )
  tool = Svndump::Compact.new( )
  def tool.node_post_hook
    if (
         # ここの書き方で調整
        )
      @storable = true
    else
      @storable = false
    end
  end
  tool.run
end

cf.


2007-09-19 [長年日記]

_ 要はどこでツッパるかってことなのでは?

※ 今回は割といろいろ読みました。

今回の話ってマシン語という単語だけ抜き出しても賛否にレベルがいくつもあって、

  1. マシン語なんて今どきムダ
  2. 教養としてマシン語の習得はしておいた方がよい、あるいはマシン語をやっといて損はないよ
  3. 絶対マシン語は習得しておくべき
  4. 絶対マシン語を現場で使えるべき

くらいに分かれています。そのうえで回路がどうのという話、機械の振る舞いがどうのという話にまで膨らんじゃってる。まぁ噛み合うわけがないわけで。ところでこの 3 と 4 にはものすごい差があると思うんだけど、みんなどの辺のレベルでマシン語が必要って言ってるんだろうなぁ。ちなみにぼくは CASL くらいしかまともに動かしたことのないお子ちゃまだよ。*1

これが例えば果てしなく上のレベルを求められたらみんなどうなのよ、と疑問を投げかけてみる。ヒューマンスキル、ビジネスロジック、モデリングをすべてのプログラマが求められたらそりゃそんなのおめぇネクタイ締めてる SE の仕事だろべらんめぇ、って思わないかい? 思うよね?

それと同じ気持ち悪さを上のレイヤーで仕事してるプログラマは感じてるわけですよ、今回の話って。たぶんですけど。

ただ今回、あぁそうかもなぁと思ったことが一つあって。上のレイヤーで仕事しててもオープンソースじゃない製品の相手をしなくちゃいけない場合は、マシン語レベルのノウハウは役に立つかもというか必須となるシーンは出てくるかもな、ということ。

オープンソース脳になってると、とにかくプロダクトの中を覗けるのが当たり前だから、いきなりマシン語の話が出てくるとはぁ?って思っちゃうけど、中身分かんない場合はマシン語っつーかバイナリのパターン以外に判断材料なかったりするから、マシン語云々ということではなくバイナリアンとしての体力は絶対あった方がいいと思う。

というかまさにそこ自分で苦手に感じてるところで、具体的に言うと MS 製品とかになっちゃいますけど、要は仕様として明記されてないから自分で動かして調べていかないと最終的な挙動をはっきり定義できないとか、逆に仕様には書いてあるのに実現できてないとかそういう問題を見つけても、とりあえずサポートに丸投げするしか方法がないわけです。つか追っかけてるヒマが絶対ないって分かってるから丸投げできるプロプラ製品を買うわけですけど、それ全否定されるとさすがに困っちゃうね。

話がそれた。

で、丸投げって書いたけど、いろいろ条件変えてテストしてそのレポートは送ってるわけです。最終的にサポートでも再現できて、かつごめんなさいと言われました。再現はできるけど根本的な解決策は現段階では存在しないと。ここまでの過程においてはマシン語の知識はまったく不要なんですけど、これが「この製品」を使ったサービスをお客様に提供しますということになると、サポートにごめんなさいと言われて諦められるかっちゅーとそれは違うかもなとは思います。

伝わりますかねぇ。我々比較的上のレイヤーで勝負する人間はこのとき、「この製品」以外の選択肢をまず模索します。サービスが商品なのであって、「この製品」は代替可能であるべきと考えているからです。そこはツッパるところじゃない、と。でも「この製品」に縛りを加える要素が*2あるのであれば、上のレイヤーの人間であってもツッパらなくてはいけないかもしれません。

要するに

  • まず何を実現しなければいけないのか?
  • そのために必要な技術要素は何か?
  • この技術要素に「問題」が発生したときにどのレベルに下りなければいけないのか?

を判断したうえで、マシン語が必要ならそれは本当に現場で必要なマシン語の話*3になるわけだけど、C のレベルに下りれば解決できるのであれば必要なのは C の知識だし、言語レベル的に C だけど機械の振る舞いも含めるかもしれないし、もっと上のレベルで足りるのであればそこまでが必須スキルであって、闇雲に下りりゃあいいってもんじゃないのは自明だと思うんだよね。あくまで「お仕事」としてはだけど。

つかまずだ。

まず最初に自分の立ち位置を示そう。

……。BINARY HACKS 開き直してみるか。


最後に。

「学習すべき要素」としていちばん納得したのはこれ。

shiro 『なんか論点がすれちがっちゃている感じがしてきました。私が言いたかったのは「どこまで降りることが必要か」ということよりも、「もちろん必要に応じて降りてゆく先に違いはあるけれど、全てのレイヤは同じではなく、何箇所かに強固な足場があるから、その足場を中心に学んでおくべき」ってことなんです。

odz buffer - どこまで必要か

まさに。まさにその通りだと思う。かっこいい。

/* はてなって個々のコメントに permalink ないんだっけ? */

cf.

*1 CASL って言ってる段階でおっさんなのはバレバレだが。そりゃダンプリストと格闘したりはしたけど、ただ雑誌見ながら打ってただけだし。

*2 例えば自社製品とか、あるいは業務提携の関係とか、あるいはブランドを利用したい、など

*3 ただこの場合、必要なのはマシン語だけではなくてアーキテクチャそのものだし、逆にマシン語が中途半端に分かることよりもそっちの方が大事なことの方が多いんじゃなかろうか? 本当に大事なのはマシン語なのか? 細かく説明するの面倒だからとりあえずマシン語って言っちゃってないか?


2007-09-20 [長年日記]

_ マトリクスごっこ

tcpdump with Pseudo Green Display

なぜか急にグリーンディスプレイみたいな画面で tail -f とか流してたらハッカーっぽいんじゃないか、とものすごく幼稚なことを思いついたので実践。

見ると Terminal.app にはこの色設定がプリセットであるじゃないか! なんてステキなターミナルなんだ!

実際にはクライアントマシンで実行しているので適当なログがなく、仕方ないので tcpdump を垂れ流すことにしてみた。画像はピクセライズのぼかしを掛けているのであんまり雰囲気が出ていないけど、それっぽいフォントを選ぶとなかなか情緒があってよろしい。

まぁ縦に流れ落ちてくるわけではないので、どこがマトリクスなんだという話なんだけど、どうせ読むわけではないので普段絶対使わない Papyrus とかのフォントにしてみるとまったく違う印象になって面白い。マトリクスの画面の再現性にこだわって意味のないデータを表示するよりも、意味のある生のデータをマトリクスぽく見ているところに面白さがあるんだけど、ま、どうでもいいです。ええ。

Tags: OSX 日々 Net

2007-09-21 [長年日記]

_ 「当たりの付け方」と「何を為さざるべきか」

あー。

自分もまだ何がどれとははっきり言えないんだけど、

知識からでも学べることと経験からしか学べないことの違い

じゃないですかね。なんとなくもやもやは分かる気がしますが、何もかも本で解決できるわけはないし、闇雲にただ経験を積ませりゃいいってもんでもないと思います。(そんなことは分かりきっていると言われるかもしれませんが。)

なんでこんな話をしているかというと、自分でもせめて C を知っといてほしいなぁと思うことはあるからです。*1ただ、ほしいなぁとも思うが具体的にどう役に立つか、あるいはどう役立てたらいいかは自分の中で明確になってはいません。自分が C を学んだときにはそれ自体が目的で、その知識を援用するという使い方は考えていなかったからです。*2

はて。

この状態で C を学ばせて果たして役に立つと思ってもらえるだろうか? いや、役に立つのだろうか?

今まさにここで行き詰まっています。もう一つはどこまでやらせれば十分という線引きが自分の中にできていない、という問題でもあります。そりゃなんだってできてくれるに越したことはないんだけど、

常に「今それやってもらうわけにいかない」

っつーのがまぁ現実なわけです。さてどうしたもんかと思いつつもリポジトリの話とかステージングの話とか「上の」ことばっかやってますよね、実際。だってそっちも別に「十分」じゃないし、そっちを強化することの方が戦力計算としては重要ですし、もしかすると下のレイヤーのスキルを上のレイヤーで応用できるかどうかも、実はその人次第かも知れないとも思います。なんとなくですが。本当に役に立つと言えるのだろうか?という疑問も実は自分の中にあります。

こういう話って別にプログラミングには限定されない話で、例えばクライアント PC のトラブルを解決する際の当たりの付け方なんてところにも、いろいろなレイヤーの知識とともに経験が総動員されるわけじゃないですか。でもこれってできない人はやっぱできないわけですよ。例えば「実際に今まさに使っている生の PC を相手にするとき」なんかに差が出ます。この場合、どれだけ深いレベルまで下りられるか、根源的な解決を試みることができるかということはたいした問題ではなくて、当座のワークアラウンドを即座に決断、実行して、時間の取れるタイミングを確認し、そこまでをどう繋ぐかを決定する*3ことがまず最初に求められる行動*4なのですが、これができるようになるにはそれなりに経験が必要です。何せヘルプが飛んでくるときというのはたいていトラブルの状況と同時に、そのうえで遂行中のタスクも切羽詰まっているからです。こういう状況には知識だけではなかなか太刀打ちできません。もちろん知識がなくていいという言い訳にはならないのですけど。

ここまで書いて、「問題」に対処するのに必要な力ってのは、下のレイヤーを知っているかどうかよりも、どんな武器を持っているかってことのような気がしてきました。ソフト、言語においてはバイナリアンとしての力は足腰として重要だと思いますが、我々は普段足腰で仕事してるわけではない。ただしんどい状況になってくると足腰を含めた全身の体力を求められることもある。

できれば全系統の能力をフルに発揮できる「クラピカの無敵モード」みたいな力がほしいです。でもそんなのは無理。そこで我々はこれがあればオレはやっていける、と確信できる必殺技を求めているのではないでしょうか。それがマシン語の人もいれば Perl や Lisp の人もいる。むしろ日本語という人もいる*5でしょうし、それは各自が各自の現場でもって確信するのでいんじゃねーの?と思うわけです。で、

自分が必殺技を持つことと他人にそれを習得させることはベツモノ

ってやっぱ思うわけです。だからかな、○○を学ぶべきとあまり言いたくないのは。

というか突き詰めていけばですよ。

○○をやらせるべきか否かを考えている人間ではなく、○○をやりたいぜ、やってやるぜと考えている人間の方にイニシアチブはあるんですよ。「やらせる」とか言ってる人はどうあがいたって他人の頑張りの「結果」しか受け取ることができないんだから、「やらせる」なんて言ってる連中が最も心を砕かなきゃいけないことは

楽しんでもらう、のめり込んでもらうために我々は何をしないべきか?

じゃないのか、と思うわけです。*6老害って言われるのはお互いに不幸だもの。

cf.

*1 だから C もマシン語もやっといて損はないよ、というのが自分の立場。

*2 そして最近の議論を読んで、知っていてほしいのは単なるモデルに過ぎなかったのかもしれないとも思いました。であれば何か適切な教科書はあるような気がします。(探せばどっかにあるでしょう。)

*3 かつトラブルに見舞われているユーザーに嘘でもいいから安心感を与える

*4 「外の」サポセンは違うでしょうね。あくまで「中の」ヘルプデスクとしては、です。

*5 自分はそれに近い気がする

*6 これってあれだな。経営者がプログラマの邪魔をしないとか、そういう話にもいくよね。いま自分が語ったのは教育の文脈の話だけど。


2007-09-22 [長年日記]

_ Ruby の Test::Unit で使える assertion

以下、使ったのは ruby 1.8.4 (2005-12-24) [powerpc-darwin]

ruby -e 'require "test/unit"
require "pp"
pp Test::Unit::Assertions.instance_methods.grep( /assert/ ).sort'

結果。

["assert",
 "assert_block",
 "assert_equal",
 "assert_in_delta",
 "assert_instance_of",
 "assert_kind_of",
 "assert_match",
 "assert_nil",
 "assert_no_match",
 "assert_not_equal",
 "assert_not_nil",
 "assert_not_same",
 "assert_nothing_raised",
 "assert_nothing_thrown",
 "assert_operator",
 "assert_raise",
 "assert_raises",
 "assert_respond_to",
 "assert_same",
 "assert_send",
 "assert_throws"]

pp がスキ。

pretty だから。

※ 実際には irb 上で叩いてますが、そこは適当に補完するなり。

Tags: Ruby

_ link を相対で張るのって難しいんだね

今まで手作業でカレントディレクトリにしかリンクを置こうとしたことがなかったので悩んだことがなかった。

相対パスでリンクを置こうとする場合のパスの基準は、カレントディレクトリはなくリンクを置く場所なのであった。

super
 + parent   <- cwd
    + child
            <- link
 + parent2  <- 実体

みたいなツリーになっているとき、cwd で

ln -s ../parent2 child/parent2

みたいにやっちゃいがちだけど、実際には

ln -s ../../parent2 child/parent2

にしないといけないのね。

面倒なら絶対パスにしとけと。

Tags: Unix

2007-09-23 [長年日記]

_ レゴマインドストームが Mac 対応してる

教育を語っておきながら Windows にしか対応してないなんて日本の製品みたいなこと言ってんじゃねーよと思っていたんだけど、去年出たやつが Mac でも動くじゃないか。

うわあああああ。

たけぇ。4万か。

いや別に今すぐ欲しいってほど欲しくはないんだけど、一つ障害が減っちゃったなぁと思って。

なんで突然マインドストーム?って思ったでしょ。マシン語の話をしてて思い出したのさ。マシン語で書くわけじゃないけど、今の子どもが自分たちの時代のように実機でのめり込めるような低レベルなものっつったらやっぱマインドストームだべ、と思い出したの。

Tags: Toy

2007-09-24 [長年日記]

_ 上のレイヤーに絞ってみる

odz buffer - だれかまとめてくれないかな

※ まとめる気全然なくてごめんなさい。

特定の処理系ベッタリになってもらっちゃ困るっつーのは当然上のレイヤーでもあって、

  • オブジェクト指向 = Java のオブジェクト指向と思い込む
  • 何で書いても BASIC みたいなコードを書く(BASIC は適当な他の言語に置き換えてもらっても ok)

人って意外と多いよねぇ、てなことを思いました。つかありゃいったいなんなんだという怒りを素直に表明しておきますが。

こういうのに巡り会うともっとちゃんと勉強してほしい、と強く思いますね。お前は Java の教科書(当然仕様書じゃなくて、本屋で手に入る割とやさしめの本)に書いてあったことがすべてなのか、とかいつまで変数名 8文字までなんすか、とかなんでイマドキすべて for ( ;; ) なんすか、とか。

でもこういうのって何を学ぶべきなのかなぁ。

いろいろやれ

ってことなのかなぁ。実際いろんな言語は触っておいた方がいいと思うし、自分もできればいろんなものを習得したいと思ってるんだけど、なんかすごくアバウトで、それを他の人に言ったところで、ふーんでおしまいですよね。

cf.

_ crontab モジュールで warning

RAA - crontab

を require したら怒られた。

warning: parenthesize argument(s) for future version

引数を与えるなら ( ) を書きましょう、ということらしい。

cf. [ruby-dev:17868] Re: parenthesize argument(s) for future version

@@ -111,7 +111,7 @@

   def add(str, job = nil)
     job = proc if iterator?
-    @table.push((parse_timedate(str) << job).extend CronRecord)
+    @table.push((parse_timedate(str) << job).extend( CronRecord ))
   end

   attr_reader :table
@@ -173,9 +173,9 @@
              elsif l.nil?
                f.to_i .. f.to_i
              elsif f.to_i < first
-               raise FormatError.new "out of range (#{f} for #{first})"
+               raise FormatError.new( "out of range (#{f} for #{first})" )
              elsif last < l.to_i
-               raise FormatError.new "out of range (#{l} for #{last})"
+               raise FormatError.new( "out of range (#{l} for #{last})" )
              else
                f.to_i .. l.to_i
              end

こんな感じですか。よく分かってないけど、警告は出なくなった。使ってみるのはこれからです。

……。

おっと。これ、環境変数を定義している行を無視できてないな。(MAILTO = とか使いませんか。)

@@ -136,7 +136,8 @@
   def parse(str)
     res = []
     str.each{|line|
       next if /(\A#)|(\A\s*\Z)/ =~ line
+      next if /(?:\S+\s+){5}(.*)/ !~ line
       res.push(parse_timedate(line).
               push(line.scan(/(?:\S+\s+){5}(.*)/).shift[-1]))
     }

こういうことですか。なんか二度手間っちゃ二度手間なんだけど、いきなり res.push しちゃってるからしょうがないか。parse_timedate() が解釈に失敗したときに false を返すとかすればいいのかしらん。

Tags: Cron Ruby

2007-09-25 [長年日記]

_ periodic と run-parts

Linux と FreeBSD の cron の動作の違いとして気になるところに、FreeBSD では

/etc/cron.d/*

を読まないというのがある*1が、periodic を使って month, weekly, daily なんかと同じように読み込ませることはできそう。つかまぁもっとこれらの periodic なディレクトリを活用すればいいんですけど、タイミングを自由に記述しつつ crontab ファイルの肥大化を防ぎたいわけですよ。

ついでに Linux の run-parts も調べてみたのでちょいとまとめてみる。

periodic

基本的な使い方

periodic DIRECTORY
  • 指定ディレクトリ内の実行ビットの立っているファイルについて順次実行を試みる
  • FreeBSD/MacOSX の /etc/periodic 内の monthly, weekly, daily はここから実行される
  • cron 関係のディレクトリでない場合は基本的にフルパスを指定する
  • run-parts と違い、実行した日時を出力する
  • 細々した設定を
periodic.conf

に書ける。細かい設定をしたい場合はディレクトリに名前を付けて置いて、その名前に応じて設定を記述していくとよい感じ。

これをうまく使えば Linux と同じように

/etc/cron.d/

内のファイルを読み取って実行させることもできなくはない。

ただし、Linux の /etc/cron.d/ 内に置くファイルは crontab そのものであり、実行ビットが必要ないが、periodic を使う場合は実行するファイルを置くので実行ビットが必要、という点が大きく違う。

run-parts

基本的な使い方

run-parts DIRECTORY
  • 指定ディレクトリ内で実行ビットの立っているファイルについて順次実行を試みる
  • Linux の monthly, weekly, daily, hourly はこの run-parts を利用して実現している

run-parts の解釈するファイル名には制限があるので注意が必要。まぁ man 嫁。

If the --lsbsysinit option is not given then the names must consist entirely of upper and lower case letters, digits, underscores, and hyphens.

/etc/cron.d/

Linux の cron はこの中のファイルについても crontab と同様にチェックを行う。この中のファイルは実際に実行するものではなく crontab フォーマットのファイルなので、当然実行ビットは必要ない

Tags: Cron Sysadmin

*1 ずっと気になってるんです、ワタシ


2007-09-26 [長年日記]

_ Tramp を使ってみた

Carbon Emacs(の、Panther対応版) と Fink の Emacs 22.1 を -nw で使ってるんだけど、なぜか Tramp 自体はインストールされているのに Info ファイルが入ってなかったのでマニュアル参照先をメモ。

ほんとは MacFUSE + sshfs を使ってみようかと思ったんだけど、10.3 では動かなかったので仕方なく。まぁ Emacs で使えりゃよかったんで、別に sshfs は動かなくてもいいわけだけど、なんとなく敗北感。

つかまぁ「実際遅い」し、わ、わざと負けてあげたのよっ!

……。

あーやる気出ねー。

[追記] 遅いっつーのは実際に開いたり閉じたりするときに一瞬感じるだけで、編集中は当然遅くはならない。それよか鍵認証のサーバに対して使えない*1のはなんでだorz

[さらに追記] 鍵認証だからじゃなかった。参照先を

/ssh:HOSTNAME:PATH

じゃなくて

/sshx:HOSTNAME:PATH

にしたら通った。どうも接続先の ssh サーバのバージョンによって動きが違うらしく、password 認証の機械でもダメなやつはダメだったし、両方とも sshx にしたら通った。

ssh クライアントのバージョンが古すぎない限りは、default method を sshx にしておくべきかもしんない。

(setq tramp-default-method "sshx")

ですな。ちなみに、鍵認証だろうが*2 password 認証だろうが、mini buffer には

Password for /HOSTNAME:

と出る。passphrase だから Password は入れない、とか考えちゃダメ。

cf. tramp で sshx で multihop

Tags: Emacs

*1 password 認証を許可していないのに Tramp に password を聞かれる

*2 agent使っててもそれ用の設定をしなければ


2007-09-28 [長年日記]

_ Puppet ダウンロードできる?

Puppet を試してみようと思うんだけど、どうも OSX はイマイチっぽい。でもまぁとりあえず Fink で入れた Ruby なら標準の Ruby とは動きが違うかもしれないよなーと思って落としてみようと思ったんだけど、なんかちゃんと落とせないよ? Puppet の tarball はともかく、Facter が落ちて来ないし、gem の方は両方ともダメだ。

んーなんだか急にやる気なくなったな。サイトの方も SSL の警告がやたら出てうっとぉしい。こういうのもったいないよなぁ、せっかくよさげなツールなのに。

Tags: Sysadmin Ruby

2007-09-29 [長年日記]

_ LL AHP

Lightweight Language AHP

4大LL(P言語 + Ruby)の中で自分に合ったものをオススメしてくれる。

別にこんなの特定されても構わないので結果を直リン。

Lightweight Language AHP の結果

Ruby (31%) > Perl (26%) > PHP (22%) > Python (21%)

なんかものすごくまっとうな結果が出てしまったような…。Ruby は記述性、と信じちゃいますけど、あとで言葉の定義を読み返すと(こら)変態性もかなり高い部類に入ってると思いますね。というかどんだけ偏った評価してるんだオノレは、という話ですか。

ただこれそもそも使ってなきゃ曖昧なイメージでしか答えられないし、隣の芝生がめっちゃ青く見えてたらそれをオススメされるような気がする。

普段使っている LL は複数選べるようにしてほしかった。Perl も PHP も Ruby も使ってるので。Python は使ってないから知らない、ってだけですな。PHP よりオススメされたらそれなりに面白いとは思ったけど、そういう結果にはならなかった。残念。


2007-09-30 [長年日記]

_ Yet Another Geekmonkey

Geekmonkey userscript injector

去年から個人的には Camino + Geekmonkey の環境で幸せに暮らしているんだけど、これを IE で再現しようとして躓いた。

課題はいくつかあって、

  • オリジナルの Geekmonkey ブックマークレットスクリプトは IE 6 では長過ぎて動かない。
  • [ this bookmarklet ] を使ってブックマークレット化したスクリプト内(伝わりますか?)で "var s=" として解釈してほしい "var%20s=" の部分でエラーが出る
    • 動くんだけど必ずエラーが出る*1
  • doIt() とか void() とか定義がないので怒られる

というわけでこれらを全部解決したものを以下のリンクに置いておきます。(Fastladder だとリンクになりませんね。feed リーダはそういう仕組みになってるの多いのかも?)

this bookmarklet

使い方は本家と同じです。

※ 念のため Firefox でも確認しましたがちゃんと機能しているようです。

ところで IE ってリンクツールバーっつうんですか、ここに DnD ってできないっぽいですね。最初どうすんだか分からなくて悩みました。

なぜ Geekmonkey にこだわっているかというと、localhost にスクリプトを保存してしまうタイプだとアップデートが面倒だからです。自分一人で使うだけならどうだっていいことだけど、複数の人に使ってもらおうと思うとこの Geekmonkey のアプローチはなかなか魅力的なのです。キャッシュをクリアするだけでアップデートできるんだもの。

*1 他にも % 表記の部分はあるのに、なぜここでだけ引っかかるのかは不明