トップ «前の日(02-28) 最新 次の日(03-01)» 追記

2004-02-29

_ PHPosxom

難しい感じが少し。というか元の blosxom からそうなんだけど、コードがぐちゃぐちゃで。短いのはいいんだがもう冗長で読みやすいコード以外受付られない軟弱体質なワタシ。

PHPosxom は flavor がスクリプトの引数で変わるけど、設置者の設定はどうなってんのかよく分からない。default に埋め込まないといけないんだとしたらちょっと扱いにくいな。あと本体がまだまだなので blosxom みたいにプラグインが充実していないのが最大の弱点か。blosxom でええやんというツッコミが聞こえる。。。

そうこうしているうちに「結局完成度なら tDiary なのかもしれぬ」などと思い始め、プラグインを漁り始める。なんだかいろいろあるぞ。とりあえず 1.5.4 だったものを 1.5.6 に portupgrade. blogkit なんてのもあるな。port になっていないプラグインを入れるのが面倒とかほざくのは堕落した証拠ですか、そうですか。つーか portupgrade しただけじゃ実際に動いている tDiary は新しくならないのね。tdiaryinst.rb なんてのがあるなぁ。前回そんなことしたっけか?

Tags: PHP Web

_ 宿題

  • tDiary を上げてプラグインをちょこちょこ試す
  • VikiWiki を上げて Farm と静的 HTML 出力を試す
  • PHPosxom のドキュメントをもちっと掘り下げる
Tags: 日々

_ mod_perl

Win32 もあるのね。mod_perl も勉強せんとな。うむうむ。

Tags: Perl Web

_ Hiki 0.6 リリース

Farm 機能が超魅力。バックエンドに CVS や Subversion を持ってこれるのはユニークだなぁ。まぁ細かい書き換えをちまちま commit されるとリポジトリが大変なことになりそうだけど、エンジニア心をくすぐる仕掛けに溢れている気がする。

追記:XSS 対策済みの 0.6.1 が出てます。

Tags: Tool Web

2008-02-29

_ Rswatch なんてものを書いてみました

※ 実際には3/1なのにあえて4年に一度の肉の日にぶつけて書くメソッド :)

Swatch あるじゃないですか。兄さん、時計じゃないっすよ。そんなベタなボケは要らないっすよ。ログ監視ツールっすよ。

SWATCH: The Simple WATCHer of Logfiles

でまぁこれは皆さんご存知の通り Perl で書かれてるわけっすよ。

昔からあるツールで非常に有名なわけですけど、例によって Perl なので(?)依存モジュールがいくつかあって、まぁ CPAN で入れればいいのは分かってるけど、CPAN モジュールってシステム管理的には超邪魔くさくね?といつも思ってる自分としては OS 全体のパッケージ管理システムに入ってないものは入れたくないわけっすよ。でも監視はしたいんす。ずるずる先延ばしにしてきたんすけど、決心して

Ruby で似たようなもの書けばいいじゃん

ということで書きました。

http://svn.coderepos.org/share/lang/ruby/misc/rswatch.rb

やっと動くものを CodeRepos にうpできたよ! 車輪の再発明上等!

で、ドキュメントもサンプルも何もないんでここに下書きを書いておきます。

必要なもの

  • Ruby と Ruby の知識
  • File::Tail モジュール http://file-tail.rubyforge.org/
    • 結局依存モジュールはあるわけですけど、pure Ruby 一個なのでご勘弁を。
  • 監視したいログに関する設定を Ruby か YAML で書く
  • 監視に利用するルールとアラート対象のログを見つけたときのアクションを Ruby で書く

意外にハードルが高くなってしまいました。これはひとえに

中身がまだ何もない

からです。

起動方法

Usage:
  rswatch.rb [options]

Options:
  --dry-run      -n  parse config, but no action
  --lib-file     -l  LIBFILE
  --config-file  -f  CONFIGFILE
  --config-yaml  -y  YAMLFILE
  --daemon       -d  daemon mode
  --debug        -D
  --help         -h
  --version      -v

設定を -f で Ruby の文法のファイルか、-y で YAML のファイルで与えます。-l で与えるライブラリがキモなんですがこれは後で触れます。

動作する Ruby のバージョンと File::Tail の置き方

Ruby 1.6.8 と 1.8.6 で動作確認しています。これを書いたいちばんの理由は Swatch はパッケージに入ってないけど Ruby 1.6 なら入ってるよ、という環境でどうにか監視したかったからなので、1.6 で動かない書き方は不許可、という枷を自分に課しています。そうです、あえての GetoptLong です。

File::Tail は gem でインストールできますが、アーカイブを取ってきて $LOAD_PATH の中で file/tail の階層になる場所に置いておけば、gem のない環境でも大丈夫です。一応 rswatch.rb そのものの置かれているディレクトリにもパスを通すようにしてあるので、

rswatch.rb
file/
     tail.rb

という形で置いてくれれば動きます。

設定の書き方

こういう構造の Hash を与えます。

# -*- ruby -*-

{
  # recipe name
  'simpleecho' => {
#    'disabled'   => true,
    'watchfiles' => [ '/var/log/apache22/httpd-access.log',
                      '/var/log/apache22/httpd-error.log',
                      '/var/log/messages',
                    ],
    'rules'      => 'nonzero?',
    'backline'   => 1,
    'action'     => 'echo',
    'max_repeat' => 3,
#    'ignore_first' => false,
  },
  RECIPENAME => {
  }
}

監視対象群のひとかたまりをレシピと呼びます。レシピには何をしたいのか分かりやすい、適当な名前をつけてやってください。中身は

disabled このレシピを無効とするかどうか
watchfiles 監視対象ファイル群
rules 監視ルールを1つ以上。複数ある場合はANDでチェックします。
backline 一度に参照できるログの行数。デフォルトは 1
action ルールが成り立った場合に実行するメソッド
max_repeat 上の action を何回まで実行するか。デフォルトは無制限。
ignore_first起動後最初にルールにマッチするログを見つけてもそれを無視するかどうか

ライブラリを用意してください

今のところ rule も action もお飾りのものしかありません。申し訳ありませんが

# -*- ruby -*-

module Rswatch
  class Rule < RuleBase
    #
    # [Param] Array backlog
    #
    def example( backlog )
    end
  end

  class Action < ActionBase
    #
    # [Param] String logname
    # [Param] Array  backlog
    #
    def example( logname, backlog )
    end
  end
end

こんな Ruby のファイルを用意して、この中で自由に書いてください。

rules, action に指定できる文字列はここで定義されたメソッド名になります。

で、起動時の -l オプションでこのファイルを指定してやります。backlog は backline で指定した行数分のログの中身が Array で渡ってきます。//m =~ backlog.join で一刀両断にするもよし、好きに料理してください。

残念ながらログファイルの解析に使える道具は Ruby 標準のものしかありません。Apache のログをサクっと解析したいとか syslog を手早く解析したいとかそういうことをしたい人は自分でなんとかしてください。

悩んでいるところ

ignore_first の値

ignore_first の値は変かもです。例えばトラブル復旧後に再起動したとかいう場合、最後のログがルールにマッチするものになっていることがあります。すると復旧後すぐ警告が発生する可能性があります。今のところデフォルトでこの値を true にしてあるので回避できますが、これは false にしておいて監視対象のログの種類によってユーザーにスイッチしてもらった方がいいような気もしています。

テスト段階ではログのほとんどがルールにマッチしちゃう状態になっていたので true にしていましたが、今考えると false が正しい気もします。ご意見ある方ツッコミください。

action の与え方

action の与え方は二つの点で悩んでいます。

  1. 複数の action を与えられるようにすべきか?
  2. いっそ Ruby のブロックを与えられるようにしようか?

特に二番目の点で悩んでいます。と言うのも、個人的に swatch では awk 風の書式の中で決まった処理しか書けないのが不便だなと感じているからです。exec や pipe を使って外部のプログラムは呼べますが、やはり不自由な感じは否めません。だったら Ruby でそのまま書けた方がいんじゃね? 設定ファイルで action に Ruby のブロックをそのまま書ければいいじゃんとも思うのですが、そうなると逆によくある処理を名前だけで呼び出すという方法と同居させにくくなりますし、YAML で設定を書くのが難しくなります。*1

あ、String だったら Ruby コード、Symbol だったら action名、という分け方はありかも。確か Ruby の Syck は Symbol も解釈できたはず。

Rubyist Magazine - プログラマーのための YAML 入門 (中級編)

  • データ型について
    • 真偽値と解釈されるデータは、"true/false", "yes/no" のほかに、"on/off" があります。また大文字でも CamelCase(先頭だけが大文字)でも認識されます
    • YAMLの仕様にはないですが、Syck では ":foo" のような「コロン+単語」の組み合わせは Ruby の Symbol と解釈されます。

やっぱそうだ。

Symbol って便利なんだなぁ。問題はブロックを渡された本体側でそれをどう取り扱ったらいいのかまだ何も考えていないところか。

目標

ゆくゆくはそうですね、ライブラリを目的別にチョイスしてサクッと監視できるようにしたいですよね。そのために本体から rule も action も切り離したんだから。ほんとによく使う基本のものだけ Base の方に取り込んで行く方向にしたいです。

あとあれですね。テストキット欲しいですよね。自分の書いた rule や action が正しく機能するかどうか簡単にテストできるようにしたい。どうすればいいかな。適当なログを吐くコードを書けばいいのか。むーん。

謝辞と愚痴

今回初めて Thread と fork を使いました。今までデータの加工しかしてなかったんだなーと痛感。以下の情報が参考になりました。

最初「スレッドはメモリを共有する」という言葉の意味が分からず悩みました。プロセスの場合は完全に分離してしまうがスレッドの場合は同じプロセス内なので flock みたいに行儀よく扱えば別々のスレッドで同じ変数を「扱うこともできるよ」という意味だと気づくまで時間が掛かりました。今回は共有したいものは何もないので「気にすることなかったのか!」と気づいてガックリ。しかしそのあとメインスレッドじゃないところのエラーがすぐに見つからないという事態に気づくまで妙なハマり方をすることに。

fork と Process.setsid の簡単なサンプルが見つからず、見当違いなコードを書いて悩むことしばし。それぞれの存在は知っていてもどこに何を書けばいいのかが短く的確に書かれているサンプルのなさに腹が立つと同時に、自分が Unix のプロセスの概念がよく分かっていないことがバレバレに。tty の detach ってそういう意味かーと初めて知った。*2

最終的にはスレッドも fork も明るいところでクックブックを読んだらだいぶ理解が進みました。電気を消してネットだけに頼っていたらハマった。

*1 YAML にこだわる意味はないという考え方もあると思いますが、Ruby コードを書くのが目的ではなく監視が目的であるという場合は、やはり設定ファイルが生の Ruby コードであるというだけで十分敬遠されると思うので、できれば生の Ruby コードでしか設定が書けないという事態は避けたいです。というか生の Ruby コードで設定を書けるようにしてあるのは 1.6 でも動くようにするためです。

*2 今回 stdin, stdout, stderr はあえてつぶしてありません。


2012-02-29

_ gitのcommitをbranchにぶちまける

どういうことか

  • gitのcommitを後から順番にトレースしたい

と思ったのです。git の working tree の更新は checkout や reset などでできるわけですが、トレースとなるとつまりこれらのコマンドを何回も発行する必要があります。

また reset や checkout は基本的には HEAD が変わってしまうので以前の commit に戻すには reflog から掘り起こす必要があります。そうすると何回も commit を行ったり来たりするのは単に checkout や reset を何回も発行するだけでなく合間に reflog も叩きまくりになると思います。

たぶんですけど。

で、これは面倒だなぁどうしようかなーと思ったんだけど branch に一つ一つ checkout してしまうのがラクチンかなと思いついたわけです。

こんな感じ

やってることは

  1. git log --reverse --oneline で commit を取得
  2. hash だけ抜き出して
  3. 頭に数字の prefix 付けて hash を branch 名にして checkout しまくる

というものです。

上の gist は Ruby で書いていますが、printf というコマンドがあるのをすぐあとに知ったので、Ruby を使わなくても sh + awk + printf 程度で十分実現できます。

master で実行すれば master の履歴が branch に展開されますし、どこかの branch で実行すれば同様にその branch の履歴を追いやすくなります。

何に使うのか

例えば料理番組風ライブコーディングで、この ticket の実装後のコードがこれになります、みたいな説明をしやすいかなと考えています。

単に流れを追うだけなら tig などのリポジトリビュワーを使って diff を見ればいいのですが、そのときそのときの commmit の状態を再現して実行したい、といった場合には恐らく役に立ちません。

今回の方法がたぶんいちばん簡単だと思うのですが、もっといい方法があったら教えてください。

あ、作業中のリポジトリにいきなり branch を作りまくるので、コピーしてから使ってください。

Tags: Git