ファイルシステム監視システム: inotify

Dropboxを使っていると、指定ディレクトリ以下に含まれるファイルが更新(作成、削除、編集)される度にDropboxを通して複数のファイルシステムで同期される。各PCにインストールされたDropboxのデスクトップソフトがファイルシステムを監視しているらしい。
Linuxだと、inotifyを使うことによって、ファイル監視アプリケーションを作ることが出来る。Ubuntuだと、aptにlibinotifyとかinotify-toolsというものがあるので、それらをインストールすれば良い。

inotify-toolsをインストールすると、inotifywaitとinotifywatchというコマンドがインストールされる。inotifywaitは指定ディレクトリ(指定を省略するとコマンドを実行したディレクトリ)内のファイルを監視する。inotifywatchは指定ディレクトリ内のファイルを監視した統計をコマンドを終了した時に出力する。Dropboxの様に、ファイルを監視し更新の度に何かするには、inotifywaitを使う。

$ inotifywait -m -r TARGET_DIR  # -m = --monitor, -r = --recursive
Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.

## ls
TARGET_DIR/ OPEN,ISDIR
TARGET_DIR/ CLOSE_NOWRITE,CLOSE,ISDIR

## touch test
TARGET_DIR/ CREATE test
TARGET_DIR/ OPEN test
TARGET_DIR/ ATTRIB test
TARGET_DIR/ CLOSE_WRITE,CLOSE test

## cat test
TARGET_DIR/ OPEN test
TARGET_DIR/ CLOSE_NOWRITE,CLOSE test

## echo "this is a statement" >> test
TARGET_DIR/ OPEN test
TARGET_DIR/ MODIFY test
TARGET_DIR/ CLOSE_WRITE,CLOSE test

## mv test test1
TARGET_DIR/ MOVED_FROM test
TARGET_DIR/ MOVED_TO test1

## cp test1 test
TARGET_DIR/ OPEN test1
TARGET_DIR/ CREATE test
TARGET_DIR/ OPEN test
TARGET_DIR/ CLOSE_WRITE,CLOSE test
TARGET_DIR/ CLOSE_NOWRITE,CLOSE test1

## rm test
TARGET_DIR/ DELETE test

出力をCSV書式にするにはオプションに"-c"を加える。

$ inotifywait -c -m -r TARGET_DIR/

## ls
TARGET_DIR/,"OPEN,ISDIR",
TARGET_DIR/,"CLOSE_NOWRITE,CLOSE,ISDIR",

## touch test
TARGET_DIR/,CREATE,test
TARGET_DIR/,OPEN,test
TARGET_DIR/,ATTRIB,test
TARGET_DIR/,"CLOSE_WRITE,CLOSE",test

## rm test
TARGET_DIR/,DELETE,test

出力書式をもっといじるなら、"--format"と"--timefmt"オプションを使う。

$ inotifywait --format "%T %e %w%f" --timefmt "%Y-%m-%d %H:%M" -m -r TARGET_DIR/
2010-12-11 13:32 DELETE TARGET_DIR/test1

libinotifyをPythonから使うなら、python-pyinotifyというパッケージがaptにあるのでインストールする。ライブラリ名はpyinotifyである。中身はctypesによるlibinotifyのラッパになっている。

pyinotifyを使ったコードを書けば、ファイルシステムのイベント毎に何かさせることが出来る。例えばデスクトップ通知を出したりファイルを処理して何か出力したり


$ python pyinotify_test.py

## touch test1
create  /home/saeki/TARGET_DIR/test1

## rm test1
delete  /home/saeki/TARGET_DIR/test1

MacだとKqueueFSEventsを使えばinotifyと似たことが出来るようだが、簡単に使うためのツールは見つからなかった。