LoginSignup
34
30

More than 5 years have passed since last update.

[Linux] inotifywaitを使ってファイル更新時に任意のコマンドを実行する

Last updated at Posted at 2016-07-27

[2016/07/29 追記]
systemd.pathを使えば同じことができそうなことが判明・・・orz

[2016/07/29 さらに追記]
systemd.pathからUnitにファイルパスを渡す方法が不明。できないのかな。
できないのならこのスクリプトも意味があるけど。
どなたかご存知でしたら教えてください。

事前準備

inotify-toolsをインストール (Redhat系)

yum install -y inotify-tools

ソース

watch-file.sh
#!/bin/bash -eu
trap "exit 0" 3 # QUITシグナルで停止

WATCH_DIR=$1    # 監視するディレクトリ
FILE_PATTERN=$2 # ファイル名正規表現
COMMAND=$3      # ファイル更新時に実行するコマンド

# --formatで"ディレクトリ ファイル名 イベント"の形式で出力するように指定
inotifywait -e CLOSE_WRITE -m -r ${WATCH_DIR} --format "%w %f %e" | \
while read LINE; do

  # --format指定した通りに変数に格納
  declare -a eventData=(${LINE})
  dirPath=${eventData[0]}
  fileName=${eventData[1]}

  # ファイル名パターンマッチング (マッチしなかったら無視)
  [[ $fileName =~ ${FILE_PATTERN} ]] || continue

  ${COMMAND} "${dirPath}${fileName}"

done

解説

  • オプション-mをつけないと最初のイベントで終了する。
  • オプション-rでディレクトリを再帰的に監視
  • 後で受け取りやすいように--formatオプション指定
  • bashの正規表現マッチングでファイル名の判定

使い方

watch-file.sh /data/app '^application-data-.*\.csv$' "echo" 

フォアグラウンドで実行し続けるので Ctrl+C で止める。

Redhat系OSのサービス化

inotifywaitはフォアグラウンドで継続実行されるのでsystemdサービスにする。

/usr/lib/systemd/system/watch-file.service
[Unit]
Description=Watch files and archive

[Service]
Type=simple
ExecStart=/path/to/watch-file.sh /data/app '^.*\.csv$' gzip
ExecStop=/usr/bin/kill -QUIT $MAINPID
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
systemctl enable watch-file
systemctl start watch-file

これでZABBIXとかでサービス監視もできるようになる。

34
30
1

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
34
30