LoginSignup
0

More than 3 years have passed since last update.

inotifywait でファイルを監視して通知までしたい

Last updated at Posted at 2019-07-09

Overview

inotifywait に関してはこのあたりが詳しいのでこちらを参照。
https://qiita.com/hana_shin/items/9e03ad7a40b4fd7afb67

inotifywait でファイルを監視するまでは調べるとよく出てくるけど、
モニターの結果を通知するいい感じの方法が見付からなかったので、試した。

準備

docker + centos:7 で試します。

docker-compose.yml
version: '3'

services:
  os:
    image: centos:7
    tty: true

コンテナが即終了しないように tty: true を付けてる。

起動

docker-compose up

コンテナに入る

centos7が立ち上がってるので、bashで入る。

docker-compose exec os bash

パッケージなど

yum update -y
yum install -y epel-release
yum install -y inotify-tools
yum install -y jq nc

jqnc は後で使います。

監視してみる

ファイルを準備

[root@92790f6e5f76 /]# pwd
/
[root@92790f6e5f76 /]# mkdir a
[root@92790f6e5f76 /]# echo test > /a/test.txt

実行

--format 指定がややこしいことになってますが、 \t がタブ文字に展開されないので愚直に繋いでます。
理由は後述。

シェルA
inotifywait -m --format "%T"$'\t'"%w"$'\t'"%f"$'\t'"%e" --timefmt '%F %T' /a

変更してみる

別のシェルで入って

シェルB
touch /a/test.txt

とかやると、

シェルA
[root@92790f6e5f76 /]# inotifywait -m --format "%T"$'\t'"%w"$'\t'"%f"$'\t'"%e" --timefmt '%F %T' /a
Setting up watches.
Watches established.
2019-07-09 04:28:20 /a/     OPEN,ISDIR
2019-07-09 04:28:20 /a/     ACCESS,ISDIR
2019-07-09 04:28:20 /a/     CLOSE_NOWRITE,CLOSE,ISDIR
2019-07-09 04:28:21 /a/ test.txt    OPEN
2019-07-09 04:28:21 /a/ test.txt    ATTRIB
2019-07-09 04:28:21 /a/ test.txt    CLOSE_WRITE,CLOSE

みたいに出力されます。

%e がイベント名のcsvに展開されるため、それ以外の部分をtsvにしたかった感じですね。

整形する

1行ずつのtsvにできたので、後々処理しやすいように jsonl に整形します。

シェルA
inotifywait -m --format "%T"$'\t'"%w"$'\t'"%f"$'\t'"%e" --timefmt '%F %T' /a \
  | jq -R -c '{hoge: .|split("\t")}'
シェルB
touch /a/test.txt

出力はこんな感じ。

シェルA
{"hoge":["2019-07-09 04:35:10","/a/","test.txt","OPEN"]}
{"hoge":["2019-07-09 04:35:10","/a/","test.txt","ATTRIB"]}
{"hoge":["2019-07-09 04:35:10","/a/","test.txt","CLOSE_WRITE,CLOSE"]}

1行ずつ処理する

が、このままだとまるごと1本のストリームなので、while read で1行ずつ処理するように修正します。

シェルA
inotifywait -m --format "%T"$'\t'"%w"$'\t'"%f"$'\t'"%e" --timefmt '%F %T' /a \
  | while read x; do
    echo "$x" | jq -Rc '{hoge: .|split("\t")}';
  done
シェルB
touch /a/test.txt

見た目は同じ。

シェルA
{"hoge":["2019-07-09 04:38:33","/a/","test.txt","OPEN"]}
{"hoge":["2019-07-09 04:38:33","/a/","test.txt","ATTRIB"]}
{"hoge":["2019-07-09 04:38:33","/a/","test.txt","CLOSE_WRITE,CLOSE"]}

通知

さて、これで1行ずつ json にして処理できるようになったので、とりあえず curl で投げてみます。

nc で簡易httpサーバを立てて、

シェルC
while true; do { echo -e 'HTTP/1.1 200 OK\r\n'; echo "OK"; } | nc -l 8080; done

監視を開始。

シェルA
inotifywait -m --format "%T"$'\t'"%w"$'\t'"%f"$'\t'"%e" --timefmt '%F %T' /a \
  | while read x; do
    echo "$x" | jq -Rc '{hoge: .|split("\t")}' | curl localhost:8080 -H 'Content-Type: application/json' -d @-;
  done

変更すると、

シェルB
touch /a/test.txt
シェルC

POST / HTTP/1.1
User-Agent: curl/7.29.0
Host: localhost:8080
Accept: */*
Content-Type: application/json
Content-Length: 56

{"hoge":["2019-07-09 04:44:18","/a/","test.txt","OPEN"]}POST / HTTP/1.1
User-Agent: curl/7.29.0
Host: localhost:8080
Accept: */*
Content-Type: application/json
Content-Length: 58

{"hoge":["2019-07-09 04:44:18","/a/","test.txt","ATTRIB"]}POST / HTTP/1.1
User-Agent: curl/7.29.0
Host: localhost:8080
Accept: */*
Content-Type: application/json
Content-Length: 69

{"hoge":["2019-07-09 04:44:18","/a/","test.txt","CLOSE_WRITE,CLOSE"]}

監視の結果を http で投げられました。

フィルタとか

  • inotifywait 自体にもイベントのフィルタあるし、
  • jq でフィルタしてもいいし、

そのあたりはお好みで。

ここまで書いて気付いたけど、 ファイルに落として fluentd でもいけますねこれ。
っていうかそっちの方が良いと思う(今更

おわり。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0