share facebook facebook2 twitter menu hatena pocket slack

2016.03.29 TUE

mruby-cli でディレクトリ監視ツールワンバイナリ版を作った

川原 洋平

WRITTEN BY川原 洋平

ご無沙汰しております。

tl;dr

自分の中で以下のブームが到来しております。

  • ディレクトリ監視(ファイル作成、削除、編集等のイベント検知)
  • ツールは出来るだけワンバイナリで提供したい(でも Go 言語は Hello world 準一級 = 初心者)

これからのブームを満たしてくれるのが mruby そして mruby-cli ということで、mruby 界に名を轟かすべくサンプルツールを作ってみることにしました。

リンク

参考

作ったもの

inokappa/watcher
Contribute to watcher development by creating an account on GitHub.

github.com

どんなものか

ダウンロードしてすぐ使える

もし、気になった方がいらっしゃったらこちらからダウンロードしてみて下さい。

ひとまずヘルプ

$ ./watcher --help

Usage: watcher [options]

  -h, --help            Display help.
  -v, --version         Display version.
  --path WATCH_PATH     Set monitoring directory path.

デモ

youtu.be

watcher バイナリを適当なパスにダウンロードするだけ。上のウィンドウで展開している test_dir を監視するように watcher を実行している図。

watcher を支える技術(というほどでもないけど)

ディレクトリ変更検知

#
# サンプルをほぼそのまま流用
#

    def watch
      logging('DEBUG', 'Watch starting...')
      watcher = Inotify::RecursiveNotifier.new
      watcher.rwatch(@path, :all_events) do |event|
        # puts event.inspect
        #
        # - [close_write, :close]
        # - 書き込みが発生したファイルを検知する
        #
        if event.events[0] == :close_write && event.events[1] == :close
          if event.watched_path[-1] == '/'
            logging('INFO', event.watched_path + event.name)
          else
            logging('INFO', event.watched_path + '/' + event.name)
          end
        end
      end

:all_events 以外のイベント :create を利用すると Segmentation fault (core dumped) を吐いてアプリケーションが落ちてしまう(こちらの原因調査に時間を要した…)ので、all_events を利用して、ファイルの書き込みが完了した(と思われる)イベントの close_write, :close を利用しました。

Watcher クラスを呼び出す処理

  • Watcher クラスを呼び出す処理
def __main__(argv)

  opt = Getopts.getopts(
    'vh',
    'version',
    'help',
    'path:'
  )

  if opt['v'] || opt['version']
    puts "v#{Watcher::VERSION}"
  elsif opt['h'] || opt['help'] || opt['path'] == ''
    puts "#{Watcher::HELP}"
  elsif opt['path']
    w = Watcher::Watcher.new(opt)
    w.watch
  else
    puts "#{Watcher::HELP}"
  end

end

こちらを参考にさせて頂いて、引数の処理には mruby-getopts を利用しました。

ワンバイナリ提供が必要なら mruby + mruby-cli の利用も検討したい

mruby-cli でワンバイナリツールの作り方については…

以下の記事がとても Blog 記事が参考になりました。

markdown(GFM) を変換するコマンドを mruby-cli で作ってみた
この記事は、mruby advent calendar 2015 20日目の記事です。みなさん難しい記事が多いですが、私にそういうのは無理なので軽めの内容になっています。はじめにmruby でコマンドラインツールを作成できる mruby-cli を使って、markdown を html に変換する gfmarkdow...

harasou.github.io

一回読めば、mruby-cli のツール作りの基本を理解することが出来ます。有難うございました。

実は Windows 版のバイナリを作りたかったんですが…

Windows 上でも動かしてみたいと考えて、Ubuntu 14.04 上で Windows 向けのバイナリを生成しようとしましたが…以下のようなエラーが…

... /watcher/mruby/build/mrbgems/mruby-inotify/src/inotify.c:8:25: fatal error: sys/inotify.h: No such file or directory
 #include <sys/inotify.h>
                         ^
compilation terminated.
... /watcher/mruby/build/mrbgems/mruby-inotify/src/inotify.c:8:25: fatal error: sys/inotify.h: No such file or directory
 #include <sys/inotify.h>
                         ^
compilation terminated.
rake aborted!

ちくしょー、ちくしょー。きっと、必要なライブラリが揃ってないだけなんだ、そうなんだ…。ん、Windows で inotify が動くのかとかそのレベルなのかもしれない。

とは言え…

mruby と mruby-cli を使えば Ruby DSL を使って異なる環境のワンバイナリツールを書けるというのは個人的にとてもうれしい限りです。Go 言語同様に Ruby や mruby に関しても初心者の域を出ておりませんが、Go 言語と比較すると若干慣れ親しんでいるという点で個人的には推していきたいなと考えております。

以上。

元記事はこちら

mruby-cli でディレクトリ監視ツールワンバイナリ版を作った