FluentdをWindowsで動かそうとして挫折しなかった記録。FluentdをWindowsで動かそうとして挫折しなかった記録。その1OlderNewerFluentdをWindowsで動かそうとして挫折しなかった記録。win32WindowsでFluentdを動かそうとして調べていった記録のメモです。まとめていないので起こった順に書いています。同じような事を試みて挫折した人が居たので、この意思を勝手に引き継いで3秒以上頑張ってみました。概要としては、fluentdのRuby実装、Python実装(fluenpy)、fluent-agent-liteのPerl実装とF#実装を確認した事と、Windowsでのファイル処理の排他制御について分かったことをまとめています。Windowsのファイルについては別の記事でまとめる事にして、この記事では簡単に触れる程度にします。OriginalのFluentd。Ruby実装なのでWindowsのRubyかJRubyで動くかなとも思っていたのですが、Cool.ioというライブラリに依存しており、これがNGとのこと。in_tailだけに依存しているとかならまだしも、あちこちで使っているっぽいのでひとまず諦め。次に調べたのはKLabのfluenpy。Talksで話しているのを聞いたので、動くかどうか調べてみました。残念ながらすんなりとWindowsでは動きませんでした。最初にPython2.7の64Bit版で動かそうと思ったのですが、何かどうでもいいところでこけるので32bit版で確認しました。OSはWindows7Proの64Bitです。インストーラーで普通にpythonをインストールしました。Expressを入れます。VS2010を入れると環境変数「VS100COMNTOOLS」が設定されるのですが、msgpack-pythonがどうもVS2008のビルドを想定しているのか(もしくはpipがその環境変数を参照するのか)「VS90COMNTOOLS」の環境変数を参照します。環境変数「VS90COMNTOOLS」をVS100COMNTOOLSの内容で作ります。次に以下のコマンドを実行して必要なものを入れました。他にpythonを使う用途も無かったのでvirtualenvは使っていません。インストールした環境を直接弄りました。https://github.com/KLab/fluenpy/tarball/masterこれだけだとgdbmが無くて起動しません。gdbmに依存しているPluginを使う予定はないので、今回は除外する事で対応。「plugins/in_multilog.py」をpluginsディレクトリから除きました。これで起動するようにはなりましたが、in_tailでpythonがエラーを出して動きません。理由は、os.O_NONBLOCKをWindowsではサポートしていないため(参考)。そこで、O_RDONLYに変更しました。これでノンブロッキング処理ではなくなりますが、別にこれでも動く事は動きます。これで出来るかなと思いきや、次は延々とRotateされた時の処理が走っていました。(毎回読み直しが走っていた)原因は、is_current関数で、os.stat(path)とos.fstat(fd)のst_inoを比較しており、この値が異なっていたらローテーションされたと判断していますが、Windowsではos.stat(path)は0が返ってきてos.fstat(fd)はそれっぽい値が返ってきます。そのため、常にファイルが変わったと判断されていました。こちらの対策方法は2つあります。1つはos.stat(path)をやめて毎回openし、os.fstat(fd).st_inoと比較するようにすること。1つはWin32のAPIをコールしてきちんとNTFSに沿った処理に変更することです。そもそも、Windowsでは(NTFSでは)Linuxと違い、inodeという概念はありません。Windowsでinodeと同じようなものを取得するには以下の2つの方法があります。FSCTL_CREATE_OR_GET_OBJECT_IDで呼び出し、FILE_OBJECTID_BUFFERのObjectIdというメンバを参照する。(ただしAdmin権限必須)。これはボリューム内で一意性を保証してくれます。nFileINdexLowを参照する。こちらは再起動、ボリュームのマウントしなおしで値が変わります。どこまで読み込んだのかを記録しないのであれば2でも良いと思います。そんなわけにもいかないと思うので1の方法できっちり対応するのが良いと思います。pythonからコールするにはpywin32を使います。pipでインストールできないので、sourceforgeからインストーラーを落として入れました。ActivePythonをインストールすると標準で付いてきそうです。ファイル移動(volume内、volume間)を行った場合にどういう挙動になるのかは別エントリにまとめます。これがいろんな実装を確認したところの壁になりました。Windowsでは単純にファイルをopenするとファイルの削除やrenameが出来なくなります。いう事は、ファイルのローテーションが出来なくなってしまい動かしているアプリを阻害する事になってしまいます。これを回避するためには、Win32APIのCreateFileA,CreateFileWでFILE_SHARE_READとFILE_SHARE_WRITEとFILE_SHARE_DELETEを指定する必要があります。pythonの2.7.3と3.3のソースを見てみたのですが、そーいう実装にはなっていませんでした。そもそもWin32APIは叩いておらず、POSIX準拠のopenを呼んでいるようです。POSIX準拠のopenではこのオプションを指定できません。Windows固有の処理なので、まぁ当然と言えば当然ですが。(参考はこちら)RubyやPerlのWindows実装はまだ見ていないのでわかりません。いうわけで、これを回避するためには、win32pyのwin32fileを使ってCreateFileWでファイルをopenし、ReadFileでファイルを読み込む必要があります。これを対応すればfluenpyはそれなりに動くようになります。ruby版のin_tailと違ってposを保存していないので、そこは追加で実装する必要があります。out_forwardの実装が、毎回socketを開いているのでそれは良くないなーと。ConnectionPoolしないとひどい事になりそうです。ここまで調べて、前職で大変お世話になったmhnsrさんに、fluentd-agent-windows-liteというものを教えていただきました。F#の実装のようです。やばい、短いソースなのにぜんぜん読めない!!!ので勘を頼りに見てみました。.netのFileStreamを使っていますが、以下のように呼び出しており、FileShare..Deleteが指定されておりません。FileShare.ReadWrite)これは、もともとローテーションを考慮していないような気もするので(すいません、本気でF#処理の流れがおえないです・・・)そーいうものなのかなと。いう訳でこれを使うのも諦め。最悪Javaで再実装しようとも思ったのですが、結局のところはWindowsのopenの排他制御で詰む予感がぷんぷんするので、fluenpyをベースにやって、どうしてもダメだったらC#でfluent-agent-liteのようなものを実装しようかなと思います。fluenpyのwin対応は落ち着いたらgithubにあげます。現状ではfluenpyをwindowsで動かすことには成功していますが。́・ω・`)あとはPerlとRubyのWin版のソースを調べてFILE_SHARE_DELETEを使えるかどうかの確認をしておこうかなと思います。Win32APIなんて久しぶりに見ました・・。それにしても、Win32APIのほげほげExというセンス(ryひとまず、その1はここまで。21:30):Node.jsでも使われているlibuvは対応しています。こちらにIssueがあります。referenceFluentdをWindowsで動かそうとして挫折しなかった記録。FluentdをWindowsで動かそうとして挫折しなかった記録。