トップ 最新 追記

2008-08-10 [長年日記]

_ shell スクリプトと Ruby スクリプトで設定を共有する

あらためて書くほどたいした話じゃないです。

細々した仕事をするスクリプトの多くは基本的に sh スクリプトが多いと思うのですが、やはり sh スクリプトでは多少荷が重い仕事もあります。awk や sed などを使うのはまぁ常套手段ではありますが、あんまり激しくコマンドを呼び出すとそれだけ負荷が高くなっていきます。そういう場合、自分は Ruby で書き直してしまうのですが、すでに稼働中の sh スクリプトを含めて毎回同じような設定を書いていることに気がつきました。わずか数行の代入文とは言え、なんかこれ無駄な感じがします。

sh スクリプトの変数代入は基本的に以下のように書きます。

VAR=VAL

自分の場合、sh スクリプトの変数は常に大文字で書くようにしているのですが、よく見たらコレ、

Ruby の定数定義と同じじゃん

と気づきました。しかも Ruby はバッククォートを使った別プロセスの結果の取得も sh スクリプトと同じように動きます。つまり、特別なフォーマット(XML やら YAML やら)を用意しなくても、特別なパーサを用意しなくても、同じ設定をそのまま sh でも Ruby でも読み込むことができるということです。

具体的にやることは以下のように、

sh と Ruby で設定を共有するイメージ

  1. 変数定義の部分を別ファイルに切り出し
  2. sh スクリプトでは . で 1 のファイルを読み込む
  3. Ruby スクリプトでは load で 1 のファイルを読み込む

だけです。

Ruby の方で定数はちょっと扱いにくいなぁと思ったら Object.const_defined?(), Object.const_get() を使って変数に取り込むことも可能です。

最初から小文字で変数を書いて Ruby でもローカル変数として取り込めばいいじゃんという意見もあるかもしれませんけど、Ruby スクリプト側は恐らくコードと設定の分離を意識して書きたいだろうから、ローカル変数にいきなり取り込むよりいったん定数で取り込んでおいて、それを必要に応じて使えるようにしておいた方が気持ちいいような気がします。で、この処理を module に追い出してしまえば毎回書く必要もありません。うん、いいアイディアだ。

Tags: Ruby

2008-08-11 [長年日記]

_ periodic_forwarder を書いた

cron シリーズ、何個目だ?

以前から cron の管理が面倒くさいことは書いているのですが、periodic, run-parts を利用することで厳密な時間設定の必要ないスクリプトの管理は比較的楽になりました。しかし、すべてのスクリプトがシステムワイドな cron ディレクトリにあると都合の悪い場合もあります。

そこでこんなものを書いてみました。

/lang/ruby/misc/periodic_forwarder CodeRepos::Share

どういうものかと言うと、

/etc/periodic/
|-- daily/
|   `-- periodic_forwarder*  ->  periodic /BASE_DIR/foo/FILLING_PATH/daily/
|-- monthly/
|   `-- periodic_forwarder*  ->  periodic /BASE_DIR/foo/FILLING_PATH/monthly/
`-- weekly/
    `-- periodic_forwarder*  ->  periodic /BASE_DIR/foo/FILLING_PATH/weekly/

こんな感じで、システムワイドな cron ディレクトリにこのスクリプトを置いておく(実際には link で ok)と、任意のディレクトリにこれを forward して、対応する period のスクリプト群を periodic, run-parts によって実行してくれるというものです。

※ 上の例は *BSD フレーバーなシステムの話ですが、Linux の /etc/cron.*/ 方式にも対応しています。

どういう場合に便利かというと、例えば

/var/www/HOST1/
/var/www/HOST2/
/var/www/HOST3/
/var/www/HOST4/

みたいに virtual host が設定されているとして、これらの HOST ごとに異なる仕事を定期的に実行させたいときなどに威力を発揮します。

/var/www/HOST1/cron/
`-- daily/
/var/www/HOST2/cron/
`-- weekly/
/var/www/HOST3/cron/
`-- daily/
/var/www/HOST4/cron/
`-- monthly/

こんな感じで定期実行するスクリプトを置くディレクトリを用意したら、

BASE_DIR     = /var/www
FILLING_PATH = cron

となるように設定してこのスクリプトをセットしておきます。

これで、ある HOST のための cron ジョブはちゃんとその HOST 用のリポジトリの中に収めておくことができます。

設定をスクリプトと分離する処理はちゃんと書いてない*1ので、ちょっと中身を書き換えてもらわないといけないですけど。すいません。一応起動時のオプションで設定を与えることはできるようにしてあるので、お試しで動かすことはできると思います。

とりあえず自分はこれで目的が達成できそうなので、今は結構ホクホクしています。


しかしこういう、

  • オプションを指定できる
  • ディレクトリを自前でなめる

ものをシステム管理的によく書くのですが、どうも自分はこの二つが同時に入っているコードのテストを書くのが苦手です。Rake とか使ってコードを置くディレクトリからテスト用のコードを生成するとかすればいいんだろうけど、面倒くさくなってベタで書いちゃうからテストを公開できなくなっちゃうんですよねぇ。うーん。まだ全然へたくそだ。

Tags: Cron Ruby

*1 いや実際には書いたんだけど、shell スクリプトと設定を共有するという特殊な方法を考えているので現在リポジトリにはその部分は上げてません。

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

_ 高野光弘の32nd Diaryについて [takano32,TAKANO Mitsuhiroこと高野光弘(26歳、日立製作所エンタープライズサーバ事業部、日本..]

_ takano32 [うちの宮本がご迷惑をおかけしてすみません。]


2008-08-14 [長年日記]

_ NIGHT ZOO 行ってきた

NIGHT ZOO で見たキリンとシマウマ

いしかわ動物園で NIGHT ZOO という企画をやっていたので行ってきた。

今回は三脚という新たな武器を手に入れたので喜び勇んで使ってみた。しかしまともに撮れた写真は案外少なかった。そもそもこのデジカメは暗い写真をあまりまともに撮れないんだよなー。

冷静になって考えると、夜行性の動物ってどれだけいるんだろうか。やたら人はいたが、夜ならではの醍醐味はどこにあったのかなぁ。まぁそんなに暑くないっていうのはメリットだし、なんとなくお祭り気分で子どもたちはテンション上がってたけど。

Tags: 日々

2008-08-24 [長年日記]

_ Yapra で FreeNAS News の野良 feed を作った

※ 2010-06-22 に feed 生成をやめました。今は blog の feed を購読してます。

FreeNAS


先日からちょっと気になっていたことがありまして。それは何かというと、なんでオレ FreeNAS の情報に疎いんだろう?ということなんですが、はたと気づきました。

Feed 購読してねぇ! てゆーか News の Feed がねぇ!

で、ないものは作ろうと。

ブツはこの上の階層にあります。

FreeNAS News unofficial feed

ここの日記データは毎日昼過ぎくらいにバックアップしてるんですけど、そのとき同時にこの feed を更新することにしました。つまり1日1回。まぁそんなもんでいいかなーと。

※ 本当は最初は Yahoo! Pipes で作ろうと思ったんですよ。自分で feed を更新し続けるのもだるいし、Yahoo! に任せちゃえと思ったんですが、なぜか Fetch Page しても failed to parse non HTML page と怒られまして。試しに validate サービスに掛けると怒られるんで、なんか途中に utf-8 じゃないコードが混ざってるんだろうなぁと思って*1 自分の手元でやってみることにしました。

で、これの作成に先日から入れ込んでいる yapra を使いました。YAML ファイル(これなんて呼ぶの?)は以下のようになります。

- module: Feed::Custom
  config:
    base_url: http://www.freenas.org/
    url: http://www.freenas.org/index.php?option=com_content&task=category&sectionid=1&id=1&Itemid=24
    extract_xpath:
      capture: //table[@class="contentpane"]
      split: //tr
      raw_date: /td[1]/text()
      title: /td[2]/a/text()
      link:
        first_node: /td[2]/a
        attr: :href
    apply_template_after_extracted:
      title: <%= item.title.strip %>
#      link: <%= (@plugin_config["base_url"] + item.raw_link) if item.raw_link %>
      date: '<%= ( item.link ) ? DateTime.parse( item.raw_date ) : DateTime.now %>'
- module: Filter::grep
  config:
    regex: '[^\s]'
    attribute: link
- module: Filter::EntryFullText
  config:
    extract_xpath:
      raw_content: //table[@class="contentpaneopen"][2]//tr[2]/td/*
    apply_template_after_extracted:
      content_encoded: '<%= ele = Hpricot( item.raw_content ); ele.search( "script" ).remove(); ele.to_html() %>'
- module: RSS::save
  config:
    title: FreeNAS News unofficial feed
    about: http://www.freenas.org/
    link: http://aligach.net/diary/
    filename: /PATH/TO/FEED

ぼくにも EFT できたよ!

でも実は不満があって、気づいた人は気づいたと思いますが、date がうまくセットできんのです。何かの拍子にうまくセットできたときがあったように思うのですが、なんかアレコレいじってるうちに二度とうまくいかなくなってしまいました;_;(レベル低すぎ) 結構いろんなパターンで試したのですが。

いい加減イヤになって、date 待ちで公開しないよりはできた分で公開しちゃうことにしました。

で、これに関係して不安があって。というのも date がセットできない状態で1日1回更新してたら毎回全 item 更新扱いにならんかな?と。ということでまず自分でこの feed を購読して確認してみます。大丈夫そうなら報告します。

こうすれば date セットできるよ!という情報もお待ちしております。というか直したついでに代わりに feed をホストしてくれると大喜びします。

あー疲れた。もっとサクっと作れるようになりたいよ。

[2008-06-25 追記] なんか最新の item が問答無用で更新されたことになってしまう感じがしますね。やっぱちゃんと date 入れないとまずいなー。

できました。しごく単純な話で date に空のもの入れちゃダメってことでした。

今回 Feed::Custom の capture で抜き取った中身(tr, td)には News とそうでないものが混ざっています。だからこそ link と date をいったん別な変数に保存して改めて apply_template_after_extracted で正しい値をセットしているのですが、このとき毎回呼び出される date: <%= %> の中で空のデータをセットしようとする場合があり、そこでコケていました。うーん。

※ これ実は extract_xpath が今の形でなければもっと簡単に書けるんですけど、その話は次回にします。

[2008-09-03 追記]

いつの間にか link に絶対 URI がはまるようになっていたので対応。

[2008-09-06 追記]

content から <script> を除去。どうも spam 対策に script に毎回違うパラメータを埋め込んでメールアドレスを表示していたらしく、その部分の HTML が毎回変化していっつも新着情報として表示されていた模様。

奥が深い。

でも Yapra::Plugin::MechanizeBase を積んだ Yapra は Hpricot でグリグリし放題だから楽ちんだね! (正規表現だけで正確に <script> だけ除去しろと言われたらイヤだ。)

*1 以前 nkf 2.0.4 辺りでテキストじゃないコードが混ざっていると落ちて fetch した HTML をまったく処理できなかったという経験があるので、似たようなもんかなーと。

本日のツッコミ(全4件) [ツッコミを入れる]

_ Yuanying [date: '<%require "date";%><%= if item.raw_link; DateTime.s..]

_ wtnabe [おぉ、ありがとうございます。そうなんですよね、なんか普通にオブジェクトを渡せたような気がするのですが、パタッと動かな..]

_ wtnabe [できました。require 'date' はなんか要らないみたいですけど、これはバージョンによるのかな? あちこち..]

_ Yuanying [おお、dateがきれいにまとめられてるw]