Hatena::ブログ(Diary)

ブックマクロ開発に このページをアンテナに追加 RSSフィード Twitter

2012/01/19

eneloopの違いまとめ。種類を調べた。比較した。

エネループが種類多すぎてよく分からないので調べてみた。エネループには種類が多すぎる。

f:id:takuya_1st:20120119142646j:image:left

f:id:takuya_1st:20120119142646j:image:left

f:id:takuya_1st:20120119142646j:image:left

f:id:takuya_1st:20120119142646j:image:left

f:id:takuya_1st:20120119142642j:image:left

f:id:takuya_1st:20120119142643j:image:left

f:id:takuya_1st:20120119142644j:image



気にするべきポイント

エネループ世代別
発売時期によって異なる、市場には旧バージョンがあふれている
最新版はマイナーチェンジ版がおおい
さらに種類が増えた
充電器との組み合わせ
充電器にも旧版新版がある。


(1)エネループには世代別に3種類ある。

f:id:takuya_1st:20120119144947j:imagef:id:takuya_1st:20120119144950j:imagef:id:takuya_1st:20120119144951j:image
最古版エネループ旧版エネループ最新版エネループ

発売時期で細かい差異がある。互換性はある、性能も大きく変わらないので、神経質でなければ気にすることではない。


見分け方のポイントは回数。最新版と旧版は充電回数の表記が違う

1500回と書いてる物は古い。現行は1800回。

旧版の方が安い。だからその辺は随意に。次回からパナソニック版になる。だからまた新旧の差で混迷を極める。


ポイント
1800回と書いてあったら最新版。それ以外は旧版。ただし旧版の方が安く買えることが多い。

(2)最新版エネループには3種類が充電容量別にある。

見た目でぱっと違いが分かる3種類。

3種類あります。

  • eneloop
  • eneloop lite
  • eneloop pro

eneloop
現行通常版
lite
価格を下げたもの。その分容量少ない
pro
容量を大きくした。その分値上がる

これらは、通常版をベースに用途に応じた使い分けが出来るようになっている。

これはそれぞれに単3・単4がある。

見た目での区別。
eneloopeneloop-liteeneloop pro
f:id:takuya_1st:20120119142646j:imagef:id:takuya_1st:20120119142642j:imagef:id:takuya_1st:20120119142644j:image

eneloopeneloop-liteeneloop pro
1900mAh950mAh2400mAh
1800回2000回500回
基本のeneloop eneloop lite
Liteは容量50%ダウン。
その分安価。
繰り返し性能10%UP
eneloop pro
Proは容量25%アップ、
その分高価
繰り返し性能75%ダウン
USB出力で使うと便利そう

用途別になっているので、用途が分からなければ通常版を買うのがよい。

(3)ただし色はアテにならない

http://ec2.images-amazon.com/images/I/61uXQW60PJL._AA1095_.jpg

http://ec2.images-amazon.com/images/I/811sjHNAY0L._AA1500_.jpg

http://ec2.images-amazon.com/images/I/81-FuL0P6eL._AA1500_.jpg


限定カラーとかあるから、基本色以外の色はアテに出来ない。


基本色以外を買うと、色で区別できなくなるよ!


(4)マイナーチェンジ版のplus

f:id:takuya_1st:20120119142643j:image

eneloop-plus

特殊マイナーバージョンとしてのPlus


性能は通常のエネループと変わらない

eneloop plus は 通常のeneloopをより安全性を高めた商品。正直なはなし、存在価値が分からない。Appleみたいに従来品を廃止してEneloopを全部Plusに置き換えたら良いのに。


充電池についてのまとめ


eneloop基本バージョン
1800回 1900mAh
eneloop 旧バージョン
 1500回
eneloop 最古バージョン
 1000回
eneloop plus
より安全性を高めた付加価値商品。
eneloop lite
容量さげて、手軽に買える。廉価版
eneloop pro
容量がほしい人向け。ただし充電回数少なめ。


(5)充電器について

充電器についても知っておく必要がある。

充電器も種類が多い。

f:id:takuya_1st:20120119150253j:image

(三洋電機カタログより)

これにさらに旧バージョンや特殊形状が存在する。

(6)エネループ充電器には標準充電器がある。

f:id:takuya_1st:20120119150255j:image

NC-TGN01
これがエネループの充電器の比較の基本

今のところこの型番を基準に考えればいいみたいですね。

(7)値段と機能の違い

NC-TGR01とNC-TGL01の違い。

(廉価版)

f:id:takuya_1st:20120119150256j:image:left

f:id:takuya_1st:20120119150257j:image

安い方を買ったときには、性能が50%ダウン、だから値段も50%ダウン。

  • 充電時間が2倍以上かかる。
  • 1本で充電できない。
  • その分価格は安い(50%オフ)

充電時間は2倍時間がかかる、2本ペアになる、だから価格も50%オフ。

高い物はドコが違うのか
  • 1本ごとに充電完了が分かるモニタ搭載。
  • バッテリーチェッカーが一本分搭載。
  • 3倍速充電対応。

高い価格帯の商品にがついています。*1

f:id:takuya_1st:20120119150300j:image
(エネループ2倍速三倍速充電器)

(8)急速・高速充電対応

3倍速と2倍速があるです

f:id:takuya_1st:20120119150303j:image
(ハイーチェッカ)
f:id:takuya_1st:20120119150304j:image (ハイー高速充電)

これらは3倍速対応


「急速」充電対応

f:id:takuya_1st:20120119150308j:image (急速充電器ポータブル)

急速充電対応と書かれた物は基本的に2倍速。三倍速があるけれど「2倍速が急速充電器です。」


(9)エネループプロ充電器は?

エネループプロ充電器は通常の物です。色違い。型番はすべてNC-TGR01です。

f:id:takuya_1st:20120119150306j:image
(エネループプロ充電器)
f:id:takuya_1st:20120119150310j:image
(エネループプラス充電器)

f:id:takuya_1st:20120119150300j:image
(エネループ2倍速三倍速充電器)

プラス専用とプロ用と書いてあるけど、通常のエネループ充電器と同じ型番です。

充電器のまとめ

廉価版=基本版 - 急速充電機能なし = 1000円
高価版=基本版+充電チェッカー + 一本単位での充電チェック
携帯版=基本版  の半分サイズ、充電は2本単位

プロ用やプラス専用はその色だけ。中身は同じらしい


エネループ買おうと思ったけどありすぎて迷う

ヨドバシカメラの店頭でも、店員に説明を受けている人が多い。僕も正直よく分からない。

鉄則
最新版のセットを買う。

ライトは安いけど充電時間かかりすぎて使えない。

最後に挿したのどれだっけ?

継ぎ足し充電ができるeneloopの特性上使い終わったら、とりあえず挿しておく。おわったら取り替えるとい

カジュアルな使い方が便利。

・充電しておく。

・取り出す。

・なんとなく不安だから充電しておく

・とりあえず満タンにしておく。

などのカジュアルな用途を満たすには、4本が個別に充電できて、充電済が一目で分かった方が良い。それもどれが充電済みで、まだかが一目で分かった方が便利。

なので充電済ライトが個別に光る物を選ぶべきです。



Amazonでは、デザインが似過ぎて分からない

Amazonの写真では、形が似ていて一目で区別がつかない。

充電回数
1800回が最新版
型番
充電器の型番で種類が分かる。

(11)エネループ一覧表

これだけ見ても分かるように,種類は数限りなく存在する。

f:id:takuya_1st:20120119150305j:image (エネループ一覧表)


しかも、三洋電機からパナソニックになったので、パナソニック版エネループとかあってもう、手がつけられない。







感想:エネループは。なんでこんなことになったのか。

ブランドイメージの確立には成功した。エネループは成功。ブランドの確立とコンセプトの確率には成功した。

でも、成長を維持するのに失敗している。

顧客ニーズに応えるコトがサービスではない。好例

ラインナップの迷走、コンセプトの迷走。増え続ける種類。

顧客ニーズに応えたつもりかもしれないけれど、顧客ニーズに応えることが正しくない好例だとおもう。顧客ニーズに応えたつもりだろうけど、むしろ分かりづらいラインナップ。色もわかりにくい。

迷走するラインナップ

Lite/Pro/Plusの区別に、バージョンの違いはもはや迷走と断言する。

唯一の救いは互換性が保たれていること。しかし互換性は電池そのものの形状と電圧基準のおかげであって、三洋電機関係ないので。

「手軽に使える」という当初コンセプトが「種類多すぎて、使い分けが大変」になって崩壊してるよね。。。

モバイルブースターとエネループの充電が一カ所ですむようにしてほしいです。Qiはちょっと初期投資多すぎて困るし。電力も無駄になりそう。携帯電話が対応してたら使うのにね。エネループは「捨てない」という新しいlifestyleの提案だった。その新しさを取り戻してほしいです。



エネループの魅力が死んでしまう。こんなにラインナップがあると管理が面倒で。エネループの魅力が死んでしまう。




ジョブズなら、「もっとわかりやすく、2種類にしろ」と言ったに違いない。

もっとシンプルにやりましょう。

AmazonのAA

もしよかったら踏んでください。オススメです。

eneloop3倍速対応急速充電器セット(単4形4本付)

感謝です。

AA踏んでくださった方!感謝です!!

f:id:takuya_1st:20120121021509p:image

徹夜でエネループ調べて、その甲斐がありました。お役に立ててうれしいです。

僕の徹夜が報われた気がします。


2012-01-20追記。

色で区別とか言われたので、色を適当に買うと、区別に使えないことを明記するなど。


2012-01-25追記

なんかたくさん買っていただいたみたいです。みなさんの優しさに感謝です。

f:id:takuya_1st:20120125094436p:image

ありがとうございます。

2012-01-26 追記

更にたくさんの人に買っていただいたみたいです!!!

f:id:takuya_1st:20120126160523p:image

皆さんのお役に立てて嬉しいです。みなさんの優しさに嬉しいです。

*1:ただし上記の三種類の機能が全部ついた物はないみたい

2012/01/18

Stringsコマンド:プログラム中で文字列として認識可能なものを全部表示してみる

stringsコマンドは、バイナリコンパイルされたバイナリを開き、ASCII文字列っぽいものがあれば、文字にして出力する。

バイナリディタで文字を探すなら、この方が速いかもしれない、バイナリ・アドレスは分からないけど、あるかないかはすぐ分かる


stringsコマンドやってみた

SQLiteのファイルを解析してみた。

f:id:takuya_1st:20120118165448j:image

わーい、CreateTableがいっぱい見える。


aliases.dbにつかう

postmapコマンドなどの、設定ファイルをバイナリに変換する系で、変換忘れてないか確認するのに使う。

takuya@debian00:~$ sudo strings /etc/aliases.db 
[sudo] password for takuya: 
root
webmaster
root
usenet
"|/usr/local/bin/catch "
sort
root
security

LocalStroageが便利になる、JSON.stringfy

LocalStroageにオブジェクトを入れるには、キーバリューなので、ちょっとめんどくさい。シリアライズをどうするのか


JSON.stringifyを使ってシリアライズ

そのため、JSオブジェクトを扱いたい場合は、JSON.stringifyとJSON.parseを利用するなどして文字列に変換してから利用することをおすすめします。

// 配列をJSON.stringifyで文字列に変換してから保存
var ary = ["aaa", "bbb"];
localStorage.setItem("hoge", JSON.stringify(ary));

// 取り出した文字列をJSON.parseでJSオブジェクトに変換する
JSON.parse(localStorage.getItem("hoge"));
> ["aaa", "bbb"]
http://d.hatena.ne.jp/pikotea/20101224/1293197750

JSONを取り出したりJSONにエンコするには

ブラウザ組込のJSONオブジェクトを使うと便利でしょうね



StorageEvent

Web Storage には、StorageEvent というイベントがあるそうです

// StorageEventを登録
window.addEventListener("storage", function(evt) {
  console.log("old:" + evt.oldValue + "/new:" + evt.newValue);
}, false);
http://d.hatena.ne.jp/pikotea/20101224/1293197750

WebStorageを使った瞬間にイベントが発生する。WebStrageに保存するタイミングで動作する方がテストが楽だし、コード簡潔になる。とくにGUIのクリックイベントが多発するようになると必須のイベントだと思う


参考資料

Web Storage について - へっぽこプログラマーの日記 ←おすすめ

システムのRubyの更新:DebianのAPTでインストールされた物

debian の rubygemsパッケージを更新しようとしている。


  • あるシステムでは。できる限りAptで管理するべきかもしれないし
  • あるシステムでは、ユーザーごとにRuby環境を作るべきかもしれない

でもいろいろ考えるの面倒くさい。とりあえずシステムのrubygems環境を更新したらいいよね。

ってことでやってみた

とりあえずシステムのrubygemsを新しくする

gem update --system

apt の場合、--systemであまりに新しいものを入れると、互換性の問題に引掛かもしれないので、

自己責任でやれと言われる。

やります。

$ gem install rubygems-update
$ update_rubygems

これで出来上がり。手早いですね。


ユーザーごとにRuby環境を作るには

rvmが一番楽。いろいろとやり方はあるんだし、gemのインストールとかいろいろ工夫してたんだけど、

RVMでもう大丈夫っぽい(ただしCygwin環境な人たちはCorei7以外でやらないように、ビルド時間が巨大です)

参考資料


http://d.hatena.ne.jp/r_kurain/20090725/1248523753

http://higelog.brassworks.jp/?p=244


cygwin だとこういうのを試したほうがいいかも。

http://webos-goodies.jp/archives/51106257.html

JavaからjRubyのソースコードを読み込んで使う。

JavaからjRubyを起動すると、JavaにRubyインタプリタを組み込むことが出来る。

どうやるのかなと思ってたら。

evalしろや。ってことらしい。

まじEvalしとる。

package takuya.morioka;
import java.io.*;
import org.jruby.Ruby;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

public class RubySample {

    public static void main(String[] args) {
        Ruby ruby = Ruby.getDefaultInstance();
        try {
            FileReader reader = new FileReader("test.rb");
            IRubyObject obj = ruby.evalScript(reader, "");  #script コードの実行
            System.out.println("Result: " + obj);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

RubyのクラスをJavaクラスとして使う

//Rubyのインタプリタを持ってくる。

        Ruby ruby = Ruby.getDefaultInstance();
        ThreadContext context = ruby.getCurrentContext();
       
        try {
            FileReader reader = new FileReader("test.rb"); //ソースを読み込む
            ruby.evalScript(reader, "");

            RubyClass rclass = ruby.getClass("MyDateTime"); 
            IRubyObject robj = rclass.callMethod(context,"new");
            IRubyObject obj = robj.callMethod(context,"getDateTime");
            System.out.println("Result: " + obj);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

実際に使う箇所

RubyClass rclass = ruby.getClass("MyDateTime");

使いどころ。難しい。

RubyはDSL的な処理が出来るので、Ruby書式で設定ファイル作らせて、Javaで読み込んで使うとか。

インタプリターパターンですよねぇ。使いどころは難しい。

参考資料

http://codezine.jp/article/detail/1647?p=3

http://codezine.jp/article/detail/1647?p=4

Windowsの自動ログイン設定

Windowsの自動ログイン設定はコマンドプロンプトから起動するのが手っ取り早い

controle userpasswords2

passwords の複数形に注意

これで起動すると

f:id:takuya_1st:20120118160945j:image


選択画面が出てきて

f:id:takuya_1st:20120118160944j:image

パスワード入力が必要のチェックを外して、OKを押す。

するとパスワード覚えさせるから、今のパスワードを確認のために入れてねって言われる。入力したら設定完了

LinuxのJOINコマンドがおもしろそうなので試してみた

JOINコマンドがあります。これは便利なのかもしれない。ファイルがそろっていることが前提ですけど

わかりやすい図があります。

f:id:takuya_1st:20120118160514j:image

Linuxコマンドでテキストデータを自在に操る - じっくりコトコト煮込んだみかん

やってみた。

f:id:takuya_1st:20120118160459j:image


シンプルで良いですね。


でも正直いえば、箱形選択が簡単にできるエディタ使ってたら用無しな気もする。

10,0000行とかなら使い勝手良さそうだけど、そのときはスクリプトでやるかも。

2012/01/17

MacのOpenコマンドのすすめ

Openコマンドは便利です。

alias opera="open /Applications/Opera.app"

とすればOperaがコマンドから起動します。

SpotLightで起動するより速いかもね、

Openは関連付けられたアプリを起動するので

open test.rb
open test.xlsx

などとしてもちゃんと起動する。

もし関連付けられたアプリがないときは

テキストエディットで起動される。

はてなフォトライフにアップロードするスクリプト

何で今までやらなかった。

アップロードが楽ちんに

f:id:takuya_1st:20120117203808j:image:w300

使い方

/usr/local/bin/fotolife *.png

はてなフォトライフにアップロードするスクリプト

#!/usr/bin/env ruby
#!/usr/bin/env ruby
require 'rubygems'
require 'net/http'
require 'wsse'
require 'base64'

require 'optparse'
opt = OptionParser.new
opt.on("-u","--url"){ $show_img_url = true }
opt.parse!(ARGV)

$KCODE='u'
if ARGV.size < 1 or not ARGV.all?{|e|  File.exist? e} then
  puts "usage: #{__FILE__} 画像ファイル名
          ファイル名はタイトルになる。
          タイトル指定したいときはファイル名を使えば良い。"
          exit 2
end

ARGV.each{|e|
    f_name = e
    a = File.basename(f_name).split('.');a.pop
    title = a.join('.')
    content = Base64.encode64(open(f_name).read)
    xml = "<entry xmlns=http://purl.org/atom/ns >"+
            "<title>#{title}</title>"+
            "<content mode='base64'  type='image/jpeg'>#{content}</content>"+
            "</entry>"
    username, password = %w!hatena_id my_password! ##←ここにID/PWを書く
    http = Net::HTTP.start("f.hatena.ne.jp", 80)
    response = http.get('/atom',{'X-WSSE' => WSSE::header(username, password )})
    response = http.post('/atom/post',xml, {'X-WSSE' => WSSE::header(username, password )})
    response.body =~ /<hatena:syntax>([^<]+)<\/hatena:syntax>/
    foto_id = $1
    puts "[#{foto_id}](#{title})" unless $show_img_url
    if $show_img_url then
      user = foto_id.split(/:/)[2]
      f_id = foto_id.split(/:/)[3].gsub /j/, ""
      puts "<img src=http://cdn-ak.f.st-hatena.com/images/fotolife/t/#{user}/#{f_id[0,8]}/#{f_id}.jpg />"
    end

}

アップロード

f:id:takuya_1st:20120117204035j:image

楽ちん。

Automatorと組み合わせて、ドラッグドロップで送信できてもいいかも。


2012/03/06改訂

-u オプション
IMGタグ生成

をつけた。-u なしだと、はてダ埋め込み用の専用タグになるようにした。

実行例

フォトライフは面倒くさいのです。ブラウザのアップロードから写真埋め込みまでがとても面倒。はてなダイアリに写真を載せるのがとても面倒だった。

これでとても簡単になった。

2012/01/16

オレオレDropBoxをrsyncで作る。

DropBoxは便利らしい。でも同期遅いし、アカウント必要だし。なにより手元に2TBのHDDが転がってる物を生かしたい

ファイル監視して、rsync起動

 #!/usr/bin/env ipyw
 from System.IO import *
 import subprocess
 
 path = "C:\\Program Files\\MySync Suite\\Users\\User0001\\Album"
 fsw = FileSystemWatcher()
 fsw.Path = path
 def watcherhandler(*args):
         subprocess.call('rsync -avz --delete -e "ssh -i /home/takuya/.ssh/id_rsa -o StrictHostKeyChecking=no " {0} takuya@s1:~/casio  '.format(path) )
 
 fsw.Changed += watcherhandler
 fsw.Created += watcherhandler
 fsw.Deleted += watcherhandler
 fsw.Renamed += watcherhandler
 fsw.IncludeSubdirectories = True
 fsw.EnableRaisingEvents = True
 
 while(True):fsw.WaitForChanged(WatcherChangeTypes.All, -1)

ファイルディレクトリの変更を監視、変化に応じて、rsyncを起動してファイルを転送する。

FileSystemWathcer
細かい説明は別エントリに書いた-----> ironpythonWindowsのフォルダを監視する。

rsync の細かいオプションは重要。

-o StrictHostKeyChecking=no
known_hostsにないホストだったらYES/NOだすかどうか→無視
-i path/to/key
id_rsaのキーファイル。WindowsのSYSTEMはフルアクセス(これは無条件でそうなる)でもほかユーザーから読めないこと必須。
takuya@servername
転送先へのログイン名。そのままだとSYSTEMになってしまうので。

あとはこれをサービス登録して

cygrunsrv --install MysyncWatcher --path `cygpath -wa /home/takuya/bin/wacher.py` --chdir `cygpath -wa /home/takuya/bin/`

常駐しておけば、Mysync suiteで同期するたびにファイルがバックアップされる。


たったこれだけでも相当便利な気がする

NASで良いジャン?

ちがうんだよ。NASだと読み込み遅くて邪魔くさいんだよ。


なにより、ネットワークに左右されない。

ファイルが出来たタイミングで同期する。コレが重要。たとえば、「CDを取り込んだら転送。」「写真を取り込んだら転送」「ソースコード編集したら、送信」


ScanSnapとの組み合わせが理想的か。

ScanSnapと組み合わせてファイルと転送したり、ファイルを変換したり、メールに送ったりできるね。ScanSnapのソフトウェア更新を待たなくてよくなる。


応用範囲は幅広い。

eo Myポータルの請求書をスクレーピングした。DropBoxに明細PDF送ってほしいわ

「請求書出来ました、"ここ"にアクセスしてください。」そんなメールは要らない。おまえらもスクレーピングしてやる。


eoのMyポータルの請求内訳を直接取得する。だって、ロード長いし、クリック多くて面倒なんだもん。

require 'rubygems'
require 'mechanize'
m = Mechanize.new
#ログインページ
m.get 'https://my.eonet.jp/tctrpp/LoginAction.do'
m.page.forms[0].fields[0].value= "eoログインID"
m.page.forms[0].fields[1].value= "パスワード"
m.page.forms[0].submit
#初回ロード
m.page.forms[0].action="/prtct/mp/mp.do"
m.page.forms[0].submit
#セッション登録
m.get 'https://my.eonet.jp/prtctp/MKA10V010Init.do?hyoujShubt=0'
#ページ移動
m.get 'https://my.eonet.jp/prtct/mk/mka10/MKA10V010.jsp'
body = m.page.search('div#contents')
#保存
open('eo請求内訳.html',"w"){|f|  f.write body}

これでOK.

請求書のWEB確認はめんどくさい。

各企業のWEB明細は、クリック多くて面倒だし、戻る禁止とか訳が分からない。たかが請求情報だけのために、どれだけ制御するんだろう。

請求データをメールで送ってくれれば良いのにな。直接開けるリンクすらCookie切れで頻繁にログインし直しになる。OAuthでRead権発行されれば、明細スクレーピングのポータルサイトが戦国時代になるのに。

eoはWEBアクセス手順が煩雑で

eoポータルはAjax/jQueryにparant.docmentにiframeといった、javascriptの新旧技術がてんこ盛りでカオスだった。あの設計はメンテできないだろう。だから、さらに5年は使われると思う。なのでこのスクレーピングも寿命は長いんじゃないかな。と


DropBoxにPDFを送ってほしい

DropBoxにPDFが届くとか、Evernoteに送信されるとかでも良いんだよ。


Windows Liveの書き込み権限をあげるから、ファイルを毎月置いてくれ。それだけいい。それで十分に感動できる。

せめて、毎月のデータくらいは簡単にアクセスできるようにしてほしいなぁ。

Windowsのフォルダを監視する。IronPython の使い方とサンプル

Windowsのフォルダを監視して、更新があったら取り込む。

というよくある処理。これを簡単にしたいなと思った。

Windowsのフォルダ監視は.NetFrameworkが楽ちん

.NetFrameworkが恐ろしくシンプルで簡単です。


from System.IO import *

path = "C:\\Users\\takuya\\Desktop"
fsw = FileSystemWatcher()
fsw.Path = path
def watcherhandler(self,*args): print args

fsw.Changed += watcherhandler
fsw.Created += watcherhandler
fsw.Deleted += watcherhandler
fsw.Renamed += watcherhandler


fsw.EnableRaisingEvents = True
while(True):fsw.WaitForChanged(WatcherChangeTypes.All, -1)

本当に、簡単です。

起動は

ipy sample_watcher.py

仕組み

.NetFramewokは、IronPythonから使える。

IronPythonはPython2.7を.netで実装し直したもの。2.7なら全機能が使える。

FileSystemWatcher は .net提供のライブラリ

IronPythonは

IronPhythonはCodePlexからダウンロードして使う。

ironpythonはインストーラーでもバイナリでもどちらでもおなじ。PATH通せば良い。

あとはipyコマンドで、インタラクティブシェルを起動すれば遊べる。


インストーラーなしで.netFrameWorkのスクリプトを書けるから、管理者権限無くてもプログラミング環境が入手できるのでウルトラ便利。

個人用途ならvbs使うよりオススメ。WindowForms作ったりさえも出来る。もちろんexe化も・・・


ironpythonからの.net クラス利用

名前空間と参照をインポートする。インポートは次のpythonコードになる。

import SystemIO.*
from SystemIO import *
二つは微妙に違う。

import SystemIO.*の場合は

SystemIO.FileSystemWatcher()

でアクセス可能。

from SystemIO import * の場合

FileSystemWatcher()

でアクセス可能

このへんはPythonのimport と同じで、上手に融合してる。

クラスの初期化

FileSystemWatcher()

()をつけるだけ。newなどはしない。

これだけ知ってれば良い。

イベントハンドラの登録

def watcherhandler(self,*args): print args

fsw.Changed += watcherhandler

演算子「+=」がイベントハンドラ登録になっている。

演算子「-=」がイベントハンドラ削除なのは、想像通りで直感的。

FileSystemWactherについて

使い方はシンプルで

の流れになる。ただし、マルチスレッドで使うので、監視を初めても、メインスレッドをロックしないのです。

代わりに、次のメソッドでイベントキュー待ち

fsw.WaitForChanged(WatcherChangeTypes.All, -1)

ずっと監視するなら、while(1)で無限ループ

while(True):fsw.WaitForChanged(WatcherChangeTypes.All, -1)

ファイルに変化があったらプロセス起動

.NetFrameworkでプロセス起動しても良いんだけど、せっかくpythonなので、

import subprocess
subprocess('sh rsync.sh")

とかやるとうれしいかも。良いとこ取り!


詳しくは、MSDN見ろってことだけど、MSDNなんてドラクエ2のラストダンジョンなみに迷路だし、妙なエンカウント多い。記号も多いからなれるまで大変な感がある。


FTPでファイルが届くのを待つだけの仕事で

設定ファイルやら、ジョブネットが時間起動だったりして面倒だったし。

cronやタスクスケジューラーでファイルが届くのを待つ。そんな仕事を山ほどやりました。POLLモデルはどうも好きになれないけど、いちからこう言うスクリプトと書けるほど実力もなかった。悔しかった。でも今ならぱぱっと書けるようになった。正直うれしかった。


参考資料

http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=5143&forum=7

http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx

IronPythonの世界 (Windows Script Programming)←おすすめ

2012/01/14

MacVim(mvim)をHomeBrewでインストールする。

brewでいれたMacvimがなんか動かないと思ってた。

f:id:takuya_1st:20120115052307p:image

macvimのインストール方法が間違ってて、やり方を見なおしたら動いた。

macvimのhomebrewインストール

macvimにも色々ある。なれないうちはhomebrewで簡単処理。

brew install macvim

MacVim.appが使えないと意味が無い。

アプリケーション・ディレクトリにMacVimを突っ込む。

takuya@air:~$ brew linkapps
Linking /usr/local/Cellar/macvim/7.3-63/MacVim.app

これでリンクが作られる。

起動方法

このアプリで開くで選択できるよ

f:id:takuya_1st:20120115052853p:image

またはコンソールから

ターミナルでは

mvim

と叩けば起動できる。




インストールには

mkdir ~/Applications

が必要かもしれない

RefeコマンドでRubyDocを簡単に使える

ちょっとあれ、どうだったかなとか考えたときにRefeが便利

f:id:takuya_1st:20120114150824p:image

refeを使うとrubyのドキュメントを簡単に引ける。オフラインでも怖くない。

refeインスト

gem install refe

つかいかた

refe String

のようにクラス名を書く。

インスタンスメソッドについて詳しく知りたいときは

refe String#gsub

のように#gsub で指定する。

クラスメソッドなら

refe Time.now

のようにする。

Refeコマンドが化ける

原因は、文字コードの憶測が適当だってことで。NKFに任せれば良いし、ENV使うべきだし。

/Users/takuya/.rvm/gems/ruby-1.8.7-p352/gems/refe-0.8.0.3/lib/refe/searcher.rb

13
14 module ReFe
15
16   module Encoding
17
18     def adjust_encoding( str )
19       return NKF.nkf('-w', str) if ENV["LANG”] =~ /UTF-8/
20       if shift_jis_platform?
21         NKF.nkf('-Es', str)
22       else
23         str
24       end
25     end
26
27     def shift_jis_platform?
28       /mswin|mingw|cygwin|djgpp|vms/ === RUBY_PLATFORM
29     end
30
31   end
32 

こんな感じで良いかな。

参考

http://d.hatena.ne.jp/riocampos2/20080409/p1

Crontabの環境変数はどうなっているのか、調べる

Crontabの環境変数のポイントまとめ

  • CRONの環境変数はCRON設定の先頭に記述します。
  • Bashの環境変数と共有してないので注意。
  • ただし、以下の変数はUNIXユーザーに通常存在する環境変数なので、使うことが出来る。
    • HOME、SHELL、LOGNAME
  • そのほかはCrontablにかく

Bash環境変数と共有するなら、Cronで実行するスクリプトに環境変数を定義するべき。

わかりやすい例。

例があったので見た方が速い。

f:id:takuya_1st:20120114145816p:image

http://blog.livedoor.jp/sasata299/archives/51279219.html



Crontabの記述例。


Q.ユーザー環境変数は引き継がれるの?

A.されない

Manページによると

・HOME、SHELL、LOGNAMEが設定される、HOMEはcron設定のファイルオーナーの環境変数が使われる。


manより抜粋

crontab の動作行は、環境変数の設定か cronコマンドのいずれかである。環境
       変数の設定は以下の形式をとる:

        name = value

       た だし、等号 (=) 両側のスペースはなくても良い。 value 内部の (先頭では
       ない) スペース文字は、値の一部として name に与えられる。 value 文字列は
       引 用符で括ってもよい (シングルクォートでもダブルクォートでも良いが、揃
       っている必要がある)。こうすれば先頭や末尾の空白を値に渡すことができる。

       いくつかの環境変数は cron(8) デーモンによって自動的に設定される。 SHELL
       は /bin/sh に設定され、 LOGNAME とHOME は /etc/passwd の crontab の所有
       者 の行から設定される。 HOME と SHELL は crontab 内部の記述で変更できる
       。 LOGNAME は変更できない。

crontab の動作行は、環境変数の設定か cronコマンドのいずれかである。環境
       変数の設定は以下の形式をとる:

        name = value

       た だし、等号 (=) 両側のスペースはなくても良い。 value 内部の (先頭では
       ない) スペース文字は、値の一部として name に与えられる。 value 文字列は
       引 用符で括ってもよい (シングルクォートでもダブルクォートでも良いが、揃
       っている必要がある)。こうすれば先頭や末尾の空白を値に渡すことができる。

       いくつかの環境変数は cron(8) デーモンによって自動的に設定される。 SHELL
       は /bin/sh に設定され、 LOGNAME とHOME は /etc/passwd の crontab の所有
       者 の行から設定される。 HOME と SHELL は crontab 内部の記述で変更できる
       。 LOGNAME は変更できない。

http://www.80code.com/kb-ja/crontab.html

cronの環境変数など

ポイント

PATHとかRVM関連で必要。


HOMEとか重要、これはそのまま使える。

Crontabの曜日

dow(day of week) の 0, 7 は Sun です。

0,   1  ,   2   , 3   , 4  ,  5     ,  6    ,7
日,  月、 火、 水、 木、金、   土、 日

mod 7 = 0 になるのが日曜です。

2012/01/13

su/sudo したときの環境変数が気になったので調べた。

sudo su したときの環境変数と、自分の環境変数がどうなってるのか知りたい。

sudo su -l したときの環境変数と sudo su の環境変数がどうなっているのか知りたい。

rvm で環境作ってると、環境変数を意識しておかないとgem install しても入ってなかったり。そんなことが起きて環境ぐちゃぐちゃになるのでちゃんと意識しておきたいと思った。


環境変数をリセットしてsu / sudo するには次の方法がある。

  1. sudoersに env_reset を書く
  2. su -l オプションで su する (unixlinuxで違う?)

調べてみた。

とにかく調べてみるのが一番。

su したときと su -l したときの環境変数

f:id:takuya_1st:20120113100837p:image


左が su -l 、右が単純なsu

su と su -l では環境変数が異なる。うん、そうだよね。

su したときの環境変数 と takuya の環境変数

f:id:takuya_1st:20120113100759p:image


左がsu の環境変数 。右がtakuyaの環境変数

su だけだとtakuyaの環境変数が持ち込まれているのが分かる。


sudo su したときの環境変数と、自分の環境変数

f:id:takuya_1st:20120113100546p:image

左がsudo su の環境変数 。右がtakuyaの環境変数。

環境変数はまっさらになってる。




sudo su -l したときの環境変数と sudo su の環境変数

f:id:takuya_1st:20120113100706p:image

左がsudo su -l の環境変数 。右がsudo suの環境変数

pwdが違うのは、新しいシェルを起動したときにhomeへ移動したかどうかの違い

-l つけると新しいbashが起動するみたい。






比較しした結論。

su では環境変数はそのまま

su -l で環境変数がリセットされる。

sudoしたときは環境変数がリセットされる。(設定次第)


環境変数がリセットされるのは重要

とくに、rvmなどのユーザ固有ローカルパッケージを使っていて、システム環境を触るときに重要。


sudoしたときに環境変数を持ち越すかどうか

sudoしたとき環境変数がリセットされてるのは、次のsudoersファイルの設定の効果


f:id:takuya_1st:20120113100929p:image


sudoersの設定で環境変数をリセットして初期化して sudo しているのが分かる。


sudoersで環境変数をリセットを標準にする

Defaults env_reset,

を書いておけば基本的に環境変数リセット。

su -l の -l オプション

Macのmanには次のように書いてあった。

     -l      Simulate a full login.  The environment is discarded except for HOME, SHELL, PATH, TERM, and USER. 
             HOME and SHELL are modified as above.
             USER is set to the target login.
             PATH is set to ``/bin:/usr/bin''. 
             TERM is imported from your current environment.  The invoked shell is
             the target login's, and su will change directory to the target login's home directory.

su の -l オプションではなく "-" を使う

DebianのManには次のように書いてあった。

 su はログインセッション中に別のユーザになるために用いる。 ユーザ名を指定せずに起動した場合、
 デフォルトではスーパーユーザの ID に変更する。
  オプション引数 - を用いると、 直接ログインした場合と同じ環境に初期化される。

というわけで、「su - 」でもおなじらしい

2012/01/12

JR西日本の運行情報を監視する。

JR西日本の遅延っぷりはナイスだ。JR東日本もナイスだ。両者は良い勝負。正直いってJR西の方がひどい。西は、JR東日本に比べるとシンプル路線。相互乗り入れもない。神戸〜京都でもシンプル。奈良なんてシンプルすぎるくらいだ。なのに遅れ続ける。もはや企業文化に原因があるのだろう。

遅延情報ページもCacheヘッダを送ってくるが、 if-modified-since を送付しても無視っぽい。いつも200okしか帰ってこない。そういう企業文化なんだろう。

というわけでJRを監視。

JR西の運行情報ページに30秒に一度アクセスして、前回と内容が変わっていればメールを送ることにした。

#!/usr/bin/env ruby
$KCODE='u'
def check_jr_kinki
    require 'rubygems'
    require 'mechanize'
    m = Mechanize.new
    m.get 'http://trafficinfo.westjr.co.jp/kinki.html'
    p = m.page
    title1 = p.search('div#contents_title').text.gsub(/\d+/,"") #=> "17:40 現在 近畿エリアの運行情報です。"
    title2 = p.search('div.time').text #=> "17:35更新"
    title3 = p.search('div.unkou').text #=> "【JR神戸線】 人身事故 振替輸送開始"
    body =  p.search('div.eikyou_block').text
    return [title1,title2,title3,body]
end 
def send_notify(title,body)
    require 'rubygems'
    require 'net/smtp'
    require 'base64'
    require 'tmail'
    mail = TMail::Mail.new
    mail.to = "takuya@localhost"
    mail.from = "takuya@localhost"
    mail.subject = title
    mail.date = Time.now
    mail.mime_version = "1.0"
    mail.body = body
    mail.set_content_type "text", "plain", {"charset" => "iso-2202-jp"}
    Net::SMTP.start("localhost","25","local",nil,nil,"plain") do |smtp|
        smtp.sendmail( mail.encoded, mail.from, mail.to)
    end 
end 
require 'rubygems'
require 'daemons'
Daemons.run_proc('jr_west_checker') do
   
    ret2  = [nil,nil,nil,nil]
    ret  = check_jr_kinki 
    loop do 
        send_notify( ret[0..2].join(''), ret[3] ) if ( ret.zip(ret2).map{|i,j| i==j }.reject{|i| i==true}.size > 0 )
        ret2 = ret  if ( ret.zip(ret2).map{|i,j| i==j }.reject{|i| i==true}.size > 0 )
        sleep 30
        ret  = check_jr_kinki
        
    end 
end 

しかもDaemonsでサービス常駐させてやった。もう何も怖くない。

mechanize 本当に便利ですね。


2012-02-02追記

ブクマコメントを頂いたので返信。

id:CIA1942

「もはや企業文化に原因が」福知山線の事故がなければもう少し状況は違ってると思いますよ?/それよりも「30秒に1回運行情報にアクセス」とか病的に近い頻度だと思うのだけど。

そう?キャッシュヘッダだけ見に行っても、毎回 200 OKが返ってくるので、どうしようもないんだけど。一分に一回でもいいんだけど、電車が15−20秒単位で運行されてることを考えると、「電車まだ来ないかーっ」ってストレスから見ればたいしたことないとも思う。

何秒にするかは、相手の更新頻度と間隔を考えて見極めたらいいのであって、WEBページのScrapeのWait時間に正解はないかと思うし、病的と言われるとちょっと。。。。

特に、今日(2012-02-02)のような大雪の日、また台風の日は、JR運行情報は毎分更新がありえます。大量更新がある事故が、いつ起きるわからないので、アクセスしすぎとも言えないんじゃないかと思います。



むしろ、画像やCSSを読み込まないので、ブラウザよりは通信量もコネクションも少ない。ですし

(最後のこれ↑は、言い訳がましいですけど)

2012/01/09

RailsサーバーとApacheの連携まとめ

RailsとApacheの連携をアレコレやってみた。

現在候補は3つ

  1. Passenger
  2. Proxy
  3. fcgi/cgi

比較

比較の条件

  • 設定がRailsディレクトリに収まるか。/etc/apache2や/etc/init.dに書くのは面倒だよね。
  • インストールが簡単か。コマンド実行だけでいけるか
  • 再起動がいるか
  • 動作速度は?
手法設定がRailsディレクトリに収まるか。インストールが簡単か。再起動が不要か動作速度はraisのエラー表示
passengerxxx
proxyxxx
cgixx
fcgixxx

mod_proxyは.htaccessに設定書けない。しかも設定するたびにapaache reloadが必要。ってことで不便すぎたわ

cgiは遅い。でも設定がappディレクトリをそのままをアーカイブ出来るので良いし、ドコでも動くし。素敵だわ。

fcgiは速いけど、reloadしまくりって感じだった。

passenger はインストール面倒だし。

Apacheと連携ならpassengerは悪くない選択肢。でも可搬性がなぁ。でも、nginxをApacheの代わりに使うと、貴重なグローバルIPの80番を浪費するし、もどかしぃぃ。

一度動いちゃうと楽だから、passengerは悪くない。でも内部的にproxyしてるってのがイヤですね。cgiはエラーがInternalServerErrorにマッピングされるので・・・あぁもうどれも微妙・・・passengerは悪くない選択肢。でもインストールが。設定が

500 internal server error

CGI/FCGIだとRailsエラーがCGIの500エラーになる。なので、Railsエラーが見られない。開発中はちょっと困る。でも本番運用ならむしろ歓(?)


そもそもRailのサーバーは

2.3系からRack経由になってる。

Rackって?

PythonWSGIをお手本にrubyで実装した物

Rackがあればどうなるの

Rackが抽象化レイヤを提供してくれるので、CGI/Fcgiでも何でも来い。

サポートされてるのは次の物。

  • Mongrel
  • EventedMongrel
  • SwiftipliedMongrel -
  • WEBrick
  • FCGI
  • CGI
  • SCGI
  • LiteSpeed
  • Thin

http://rack.rubyforge.org/doc/

つまり、RaisはRackが抽象化レイヤの恩恵を受けるので、MongrelでもThinでもなんでもいいし、CGIでも良いんですね。

納得でした


apacheでやることが主眼だから、mongorel使えとか、thinの方が速いとかそういう話題には触れてないです。

Railsをmod_proxy でApacheと動かす。

railsとApacheの連携でよく紹介されてたのがmod_proxyを使う方法proxyだからApacheと連携してるとは言いがたいんだけど。まぁApacheとURLを共有できるからある意味連携かな。

railsサーバーを起動してApacheが受付になってRailsにリクエストする方式。

  • railsの起動
  • apacheの起動
  • proxy/httpの設定

が必要になる。

mod_proxyは apache2.2ではいくつかのサブモジュールに分割されてる。

proxy 経由でHTTPへ転送するには proxy httpが必要

mod_proxy はproxyを使うよってことで

mod_proxy_http は proxy 先へのプロトコルに httpを使うよ

mod_proxy_ajp は proxy 先のプロトコルに ajpを使うよってことで。


インストール

debianの場合は、apacheモジュールのインストールはとても楽

a2enmod proxy 
a2enmod proxy_http
service apache2 reload

Apacheの設定を理解するにはDebianを使うことを勧めす。httpd.confをちまちま読むCentOSスタイルだとドコの設定がどうなってるかが見通し悪くて学習には向かない。Debianスタイルは管理も楽だし、学習にも向いてる。オススメ


railsの起動

localhost に起動する。

rails server -b localhost 

proxyの設定

ProxyPass /book http://localhost:3000/
ProxyPassReverse /book http://localhost:3000/

このように書くと

192.168.1.210/bookへのアクセスは mod_proxy_http経由で http://localhost:3000へ転送される。

railsの自動起動設定

しかしこの場合欠点がある。railsの自動起動が出来ない。めんどくさーい


rubyのdaemonsを使えば良い

daemonsを使ってinitスクリプトとして動くようにして、自動起動に登録すれば良い。

my_app_init.rb
#!/usr/bin/env ruby
require "rubygems"
require "daemons" 


Dir.chdir "path/to/my/app”
Daemons.run(“rails server -b 192.168.2.1")

これで作って。

cp my_app_init.rb /etc/init.d/
rccnonf 

とでもやって、起動時に実行されるように登録すれば良い。centosならchkconfig かな



proxyって色々考えること多いからいっこで終わりませんね。

Apacheの設定のプロになってきた気がする。

RailsをPassengerモードで動かす。

RailsをApache+Passengerで動かす。

Passengerって?

RailsもつかってるRackをApacheに組み込んじゃう感じ。

mod_rackを使えるように、mod_proxyと組み合わせて内部的にrailsプロキシしちゃう。そんな感じ

aptインストール

apt-get で入ったよ。でも動かなかった。。理由は。gem依存モジュールがaptパッケージの想定違うことによるみたい。

手動で環境作る手順

  • gem パッケージでインストール
  • apacheのapxでモジュールとしてコンパイル
  • apacheにdynamic share object (so)として組み込み
  • rails環境作る
  • Passengerでrails起動

この手順がpassenger-install-apache2-module コマンドだけに集約される。えらい。

手動インストール

gemから。

gem update --system
gem install passenger
passenger-install-apache2-module 

aptで入れたパッケージは動かなかったので。

rvm環境とかあるときは注意してね

画面の指示に従う。

f:id:takuya_1st:20120109130901p:image

f:id:takuya_1st:20120109130900p:image

画面の指示が詳細でわかりやすい。こういう気配りいいよね

指示画面のキャプチャがつぶれて見えないので。

The Apache 2 module was successfully installed.

Please edit your Apache configuration file, and add these lines:

   LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-3.0.11/ext/apache2/mod_passenger.so
   PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-3.0.11
   PassengerRuby /usr/bin/ruby1.8

実際の設定

実際に設定した。

ドキュメントルートでPassengerを動かす場合

/etc/apache2/sites-enabled/air.example.jp
<VirtualHost *:80>
  DocumentRoot /var/www/air.example.jp/rails/book/public
  ServerName air.example.jp
  RailsEnv development
  <Directory /var/www/air.example.jp/rails/book/public>
   AllowOverride all
   Options -MultiViews
  </Directory>
</VirtualHost>
/etc/apache2/mods-enabled/passenger.load
LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-3.0.11/ext/apache2/mod_passenger.so
/etc/apache2/mods-enabled/passenger.conf
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-3.0.11
PassengerRuby /usr/bin/ruby1.8

ドキュメントルート以外を使う場合

ドキュメント以外のディレクトリにRailsを入れて、ディレクトリを別にする場合

<VirtualHost *:80>
  DocumentRoot /var/www/air.example.jp
  ServerName air.example.jp
  RailsEnv development
  RailsBaseURI /rails/book/public
  <Directory /var/www/air.example.jp/rails/book/public>
   AllowOverride all
   Options -MultiViews
  </Directory>
</VirtualHost>

簡単ですね。

ここまで簡単なら、自分専用に作っておいても問題ないかなーって思う。


PushionPassenger

のPhusionっての名前がすきになれない.PHPの守護神(スホンシン)パッチを思い出して・・・

f:id:takuya_1st:20120109130307p:image

この自己主張しすぎなハングルが嫌いなんだけど、これを思い出していや。関係ないのに。


passenger を見送った理由

でも、まだまだめんどくさい。コンパイルとか設定管理とか。

ユーザー管理周りがちょっと面倒

本家ドキュメントに以下の通り、ユーザー環境について書いてある。

8.1. User switching (security)

There is a problem that plagues most PHP web hosts, namely the fact that all PHP applications are run in the same user context as the web server. So for example, Joe’s PHP application will be able to read Jane’s PHP application’s passwords. This is obviously undesirable on many servers.

Phusion Passenger solves this problem by implementing user switching. A Rails application is started as the owner of the file config/environment.rb, and a Rack application is started as the owner of the file config.ru. So if /home/webapps/foo/config/environment.rb is owned by joe, then Phusion Passenger will launch the corresponding Rails application as joe as well.

This behavior is the default, and you don’t need to configure anything. But there are things that you should keep in mind:

The owner of environment.rb/config.ru must have read access to the application’s root directory, and read/write access to the application’s logs directory.

This feature is only available if Apache is started by root. This is the case on most Apache installations.

Under no circumstances will applications be run as root. If environment.rb/config.ru is owned as root or by an unknown user, then the Rails/Rack application will run as the user specified by PassengerDefaultUser and PassengerDefaultGroup.

User switching can be disabled with the PassengerUserSwitching option.

http://www.modrails.com/documentation/Users%20guide%20Apache.html#conflicting_apache_modules

日本語でOK

mod_phpにもプロセスはApacheがオーナーになるので、ファイルのパーミッションが甘い。Joeの740のファイルはJameのPHPから読めてしまう。apacheがプロセスだからだ

passengerはこのような問題を解決するために、PassengerDefaultUserをhttpdオプションに使います。云々

phpではこのような問題を解決するためにsuphpやらexeccgiを使うんですがね。。。実際使ってるホスティングは結構ある。


ってわけで、passengerでホスティングができるかもってタイトルは釣りっぽい、最初この人に思い切り釣られた悔しい。→ホスティングサービスでもRailsが利用できるようになるかも、な「Passenger」

passengerの動作原理

Phusion Passenger could create a new Ruby process, which will then load the Rails application along with the entire Rails framework. This process will then enter an request handling main loop.

Phusion Passenger calls fork(), but not exec().

Phusion Passenger will first create a so-called ApplicationSpawner server process. This process loads the entire Rails application along with the Rails framework, by loading environment.rb. Then, whenever Phusion Passenger needs a new worker process

http://www.modrails.com/documentation/Users%20guide%20Apache.html#spawning_methods_explained

適当にそれっぽい所を抜き出した。間違ってたらゴメン。

passengerはrailsをロードしてそれを、forkしてWokerを作る。Workerを作ってHTTPリクエストをハンドリングする。

つまり、ApacheのPre-forkっぽいことをPassenger内部でさらにやってる様子。ってことでApacheが起動したらPassengerのプロセスツリーもまとめて起動されるってことらしい。

プロセスツリーを見ればもう少しわかりやすい

f:id:takuya_1st:20120109130056p:image


passengerは確かに便利。一度インストールすると、無意識的に使える。だけど、Apacheを使ったシビアな設定には耐えられないかも・・・というちょっとした地雷予感がしたのでこの技術は枯れるまでスルーするかも

せめてAptGetで一発で入ってすぐ使えたらなぁ。。。apt-get のパッケージ動かなかったんで。。。

2012/01/08

railsをCGIモードで動かす。

Rack経由でfcgiで動くのなら、cgiでも動くんじゃね?

ruby on railsをCGIで動かす方が、開発時は便利そうだ。CGIで動かしてみる。

あっさり動く

これあっさり動くねぇ。

背景

fcgiだとキャッシュされすぎるので、開発には向いてないと判断。

そもそも、railsのアプリを動かすのに、ポート指定したり、自動起動設定したり、プロキシ入れたり面倒なんだよ。phpみたいにファイル置くだけで動いてほしい。

passengerとかは、一度動くと便利。だけど、インストール面倒だった。cgi最高

実験環境

  • debian squeeze
  • apache2.x
  • ruby1.8.7
  • rails3.1

で実験中

apache でcgiを有効にする。

railsが動かしたいディレクトリでcgiが動くように設定。たとえば以下の通り。

<Directory path/to/my/app>
  AllowOverride all 
  Options ExecCGI FollowSymLinks
</Directory>

.htaccessを設定する

RewriteEngine ON
RewriteBase /path/to/my/app/public/
RewriteRule ^.+$   dispatch.cgi [QSA,L]
AddHandler cgi-script  .cgi

fcgiとほとんど同じです。

dispatch.cgiを作る

ファイル名は名前は何でも良いん。.htaccessに指定した名前であれば良い。

#!/usr/bin/ruby
require 'rubygems'
require 'cgi'
require '../config/environment'

class Rack::PathInfoRewriter
  def initialize(app)
    @app = app
  end

  def call(env)
    env.delete('SCRIPT_NAME')
    parts = env['REQUEST_URI'].split('?')
    env['PATH_INFO'] = parts[0]
    #env['PATH_INFO'] = env["PATH_INFO"].sub(%r"^/book", "")
    env['QUERY_STRING'] = parts[1].to_s
    @app.call(env)
  end
end

Rack::Handler::CGI.run  Rack::PathInfoRewriter.new(Book::Application)

これもfcgiとほとんど同じ。

これだけ。

cgiが動くだけでいい。なんだコレ便利。


railsディレクトリだけを入れてるだけで良いですね。.htaccessをpublicに入れてればそれでいいですね。


一応環境確認のための virtualhost 設定

virtualhost 設定はこんな感じ。

<VirtualHost *:80>
  DocumentRoot /var/www/air.example.jp
  ServerName air.example.jp
  RailsEnv development
  RailsBaseURI /rails/book/public
  Alias  /book/  /var/www/air.example.jp/rails/book/public/
  <Directory /var/www/air.example.jp/rails/book/public>
   AllowOverride all
   Options ExecCGI FollowSymLinks
   Options -MultiViews
  </Directory>
</VirtualHost>


一部passengerの設定が混じってるけど気にしない。


Rackが対応してればRailsのベースは何でもいいみたい

rackで抽象化されているので、Railsはなんでもいいや。動作速度も大事だけど。。。。

railsの魅力は、開発速度だよね?

ITシステムにおいて一番大事なのはコスト。コストの中では一番高い物は何か。プログラムの実行時間でも、待ち時間でも、ない。

実行速度よりも大事なものがある。簡単なデプロイ?、いいや開発時の人件費。人的コストだよね。だから、簡単にコピーして移動できる方が良い。railsは開発サーバー内蔵なのでその点が楽。であれば、コピーして簡単に動かせる方が良い。PHPとかほかのシステムもカラムなら、proxyよりCGIが手軽に管理できて良いと思ったり。

rails をapache+fcgiで動かす。

Railsのために、ポート開けたり、リバースプロキシするのが面倒だし。PHPと同じようにファイル展開するだけで動いたら良いのに。

やってみたら動く。

調べたら動くことが分かった。

下準備

sudo aptitude install libapache2-mod-fcgid
sudo aptitude install libfcgi-dev 
sudo gem install fcgi

apacheにfcgiを入れてないときは、fcgiを入れる。rails持ってないときはrailsも入れてね。

実験環境

rails3.1

ruby 1.8.7

apache2

debian squeeze

そうですね。ポイントはrails3.1です。

設定の流れ

  • fastcgiが動くように
  • railsが起動してるappディレクトリを準備
  • public ディレクトリに.htaccessを設定
  • .htaccess でmod_rewrite + fcgi起動を設定。

railsディレクトリの準備

rails new bookapp
rails generate home index
rails server -b 127.0.0.1

くらいですかね。ここまでやって起動確認はやっておくと後で切り分けが楽。

.htaccessを準備する。

public/.htaccess に用意します。

AddHandler fastcgi-script .fcgi
RewriteEngine ON
RewriteBase /book/
RewriteRule ^.+$   dispatch.cgi [QSA,L]

上で指定したdispatch.cgi

実際にRailsを起動する dispatch.fcgiをruby

fcgiでrailsを起動するためのdispatch.rb

#!/usr/bin/ruby
require 'rubygems'#ruby 1.8
require 'fcgi'# ruby1.8
require '../config/environment’ #ruby1.8

class Rack::PathInfoRewriter
  def initialize(app)
    @app = app
  end
  def call(env)
    env.delete('SCRIPT_NAME')
    parts = env['REQUEST_URI'].split('?')
    env['PATH_INFO'] = parts[0]
  #必要に応じてPATH_INFOを書き換える
    #env['PATH_INFO'] = env["PATH_INFO"].sub(%r^/path/to/my/rails/public", "")
    env['QUERY_STRING'] = parts[1].to_s
    @app.call(env)
  end
end
Rack::Handler::FastCGI.run  Rack::PathInfoRewriter.new(YOURAPPNAME::Application)

PATH_INFOは、Railsを展開したいディレクトリに応じて適当に切り詰めてください。

apacheの再起動。

fcgiが設定済みなら特に再起動不要。展開に失敗したときは必ずreloadする。


fastCGIの注意点

ruby設定ミスったりrailsにエラーがあると、再起動が必要です。


fastCGIはなぜFAST(速)なのか。

それはキャッシュするからだ。mod_fcgi + ruby の場合、rubyのスクリプトファイルを読み込んでキャッシュしてる。

ファイルキャッシュは、OSレイヤでやってる。fcgiはさらにバイナリキャッシュをする。バイナリはrubyスクリプトが実行可能形バイナリに変換されたもの


つまり、単純にfcgiを使ってると、 apache reload を頻繁にやらないと、バイナリが更新されない。


逆に、バイナリキャッシュをやめると、ファイルの更新が速反映されるが、Rubyの実行バイナリへの変換が遅いので、fcgiの恩恵にあずかれない。


ってことで、、、、

fcgiは enviroment => product 専用。

dev環境で使うには、、、開発中は頻繁にファイル更新がル。ファイル更新するとバイナリキャッシュがあるので色々めんどくさい。

バイナリキャッシュの恩恵に預かれない。なのでfcgiを使うことすら無駄。ちょっと考えれば分かることだった。お疲れ様オレ。



参考資料

Linuxなら素直にPassengerを使いましょう。もしくはmongrel(+mod_proxy(_balancer))で。

http://okwave.jp/qa/q5201582.html

どの辺が素直なんだか。。。これは嘘なのです。相変わらず、ドヤ顔のOKWAVEはむかつく。


Rails 3 is built on top of Rack and Rack provides a FastCGI handler.

http://rack.rubyforge.org/doc/

http://rack.rubyforge.org/doc/Rack/Handler/FastCGI.html

http://stackoverflow.com/questions/3296206/rails-3-and-fcgi

コレが正しい回答です。

railsは3.1の今でもfcgiで動きます。

そもそも、CGIやFastCGI駆動は今は推奨されていないみたいです。

(というか、RailsでFastCGIを使うというのはどこで入手された情報でしょう?)

http://okwave.jp/qa/q5201582.html

上のちょっとドヤ顔の回答がむかついたのです。だからfcgiで動かした。

「非推奨はドコに書いてあった?」本家にはドキュメントが見当たらない。


OKWaveは第三者がみて間違ってるよと、添削したくても指摘する機能が無いので、どうしても記事が洗練されない。そのくせ、疑問点に対する回答して書かれてて、もっともらしく見えるので問題。

ちゃんとした参考資料

http://d.hatena.ne.jp/is0me/20090629/1246292165

2012/01/06

html5のW3C FileAPIについて、調べてまとめた。

html5のファイルAPIについて調べた。http://www.w3.org/TR/FileAPI/ を読みながら、メモ。やっぱり本家ドキュメントは頼りになるのね。


FileAPIはなにか

  • ローカルファイルにアクセスできる。
  • アクセスできるファイルはinput で指定された物だけ。

使い方

input に files タイプを指定するとFileAPIの対象になる。

<input type=files  >

filesタイプの読み込み方

file = document.forms[0].elements[0].files[0]

このように、<input type=files/>へJS経由でアクセスできる。


input type=filesの項目は、複数ファイルの配列になっている。FileListオブジェクト呼ぶ


FileList オブジェクト

通常の配列みたいなオブジェクトして定義されている。つまり配列だと思っておけば良い。

files = document.forms[0].elements[0].files
file.length
files[0]
files.item(0)

File。FileListの中に入ってるオブジェクト

input type=filesでユーザーが指定したファイルのオブジェクトが入っている。

File/FileListは、Iteratorパターンの関係にあるの

Fileオブジェクトでとれる物。

  • ファイル名
  • サイズ
  • 最終更新日
files = document.forms[0].elements[0].files
file = files[0]
file.name                  // => "test.xls"
files.lastmodifideDate // => ""
files.size                  //  => 1234567

ただし、内容読み込みは出来ない。


なぜか?

 input type=fileで、ブラウザがファイルを読み込んでたら遅いジャン

だったらどうするの?

 ローカルファイルすら非同期で読み込みます。

つまり?

ローカルは http:// https://のような file:// のScheme空間だと認知しておけば良い。


非同期で読み込むって?

XHRみたいに読み込めば良いんだよ。

new XmlHttp()のかわりに、new FileReader()する

何度も言うけど、非同期だからね!!

reader = new FileReader()
file = document.forms[0].elements[0].files[0]
reader.readAsText(file, 'UTF-8')#このあとはEvent処理に任せるよ!

非同期なんだから、Event処理を書いとかないとしょうが無い。
reader = new FileReader()
reader.onload     = function(evt){} //読み込み完了したら呼ばれる。
reader.onprogress = function(evt){} //ファイル読み込み中に呼ばれる。
reader.onerror    = function(ev){}  //エラー時に呼ばれる。

イベントにはどんな種類があるの?

Filereaderが持ってるイベントはこんなのがある

ハンドラ名イベント
onloadstartloadstart
onprogressprogress
onabortabort
onerrorerror
onloadload
onloadendloadend

イベントは以上です。

ぐだぐだ言わずに、ファイル読めりゃ良いんだよ

僕らはファイルを読み込みたいだけなんだ。

reader = new FileReader()
file = document.forms[0].elements[0].files[0]
reader.readAsText(file, 'UTF-8')#このあとはEvent処理に任せるよ!

///しばらく待つ。
reader.readyState //これが2になれば読み込みおわり


while(reader.readyState!=2){  }
//ファイルの中身を見る

reader.result   


readyStateとか見覚えあるよね



そうXHRみたいなもんなんだよ。


つまり

比較してみよう

データオブジェクト
Ajax URL:アドレス  Xmlhttp
FileAPI Fileオブジェクト FileReader

対で覚えるとイメージしやすいみたい。



何で非同期になってるのよ。


ファイル読み込み程度で、ほかのJSの動作をストップさせるともったいない。だからマルチスレッドで動くようにファイル読み込みを別スレッドにしてる。HTMLを読み込んでDOMを構築するときにIMGやCSSを非同期に読み込むでしょ?あれと同じことをローカルファイルでもやってる。

ってことみたい



シンプルに、覚えよう。

次の原理として覚えることにした。

ローカルファイルはfile://スキーマ。http://スキーマと同じ扱いを受ける



絶対に同期できないの?

もちろん出来る。

XMLHTTPに同期通信が用意されているように、ファイルにも同期が用意されている。それが FileReaderSync



全部非同期で良いジャン?

いや、WebWorkersでプログラマがスレッド作れるから、スレッド同期処理はあった方が良い。


部分的にファイル読込できないの?

HTTPはファイルの部分取得が出来る、FileAPIは出来ないの?

もちろん出来る。File#sliceがそれ。


まとめ

HTTPとおなじ扱いのFILEとして定義されている。

同期・非同期、部分読み込みがあるのです。やっぱHTTPと同じだよね。Fileだからといっても、思想は何も変わらない。オブジェクトが変わるだけ。





ところで、読み込んだファイルをどう使うの?

画像をインラインに埋め込む記述を覚えていますか?


     <img src="data:123456yjgbvd”/>

ファイルAPIで読み込んだファイル内容は、


     <img src=“blob:123456yjgbvd”/>

と書き込み、使うことが出来る。

data: だと base64エンコードが必要だからめんどくさいけど、blogならバイナリそのままで楽ちん。


これをblob: プロトコルと呼びます。



講釈は良いから、使い方を

説明多くてすいません。こうやります。

var file = document.getElementById('file').files[0];
     if(file){
       blobURLref = window.URL.createObjectURL(file);
       myimg.src = blobURLref;      }

1:window.URL.createObjectURL() にファイルを渡すと blob:xxxxxのURLが帰ってきます。

2:blob:のURLをimg.srcに埋め込めば終わり。

簡単ですね。




参考資料

http://www.w3.org/TR/FileAPI/

W3Cだけでかなりおなかいっぱいになれる。