黄脳エンジニアメモ

仕事や趣味やらで調べたり試したりした情報をただただ書き並べてるだけ

*

[Linux]ホットフォルダ/ファイル検出して処理をしたい

      2015/01/21

ホットフォルダ本来はどうすべきか

ファイルの検出を同期で行うのが正しいです。ファイルの作成や削除はフォルダの更新を検出すればいいのです。

本来はファイルを検出したらそのファイルが他のプログラムがopenしていないことを確認することでファイルが書き終わっている(成功してても失敗でも)と認識すべきです。それで壊れていたのならエラー処理(エラーフォルダに移動するのが鉄板)して次のファイルを処理させます。

とはいっても専用のプログラムをシステムコール使って実装しないとできないので簡単にはいきませんね。

Linuxならinotify-toolsがある

inotify-toolsはファイルサーバの同期などで使うツールですが、ファイル操作検出してくれるツールで今回はinotifywaitというコマンドを使えばあんがいすっきり実装できます。

inotify-toolsインストール

下記のようにして inotify-tools を導入すると inotifywaitが使えるようになります。インストールはrootで行います。

# yum --enablerepo=epel -y install inotify-tools

ファイル検出の方法

下記のコマンドラインで書き込み処理のCLOSEと、ファイルが移動してきたことを検知できます。

# inotifywait -e CLOSE_WRITE,MOVED_TO /tmp/hotfolder
Setting up watches.
Watches established.

この状態でこの/tmp/hotfolderにファイルをコピーしてxxx.xmlで保存すると。

/tmp/hotfolder/ CLOSE_WRITE,CLOSE xxx.xml

移動の場合は

/tmp/hotfolder/ MOVED_TO yyy.xml

検出するイベントの指定で -e  CLOSE_WRITE,MOVED_TO としていて CREATE とMODIFYは指定しません(これ重要)。ネットでこのコマンドの使い方みると多くはCREATE とMODIFYを使う例が多くみられますがこればNGです。CREATEはファイル名が登録された状態でファイルの中身は書き込み中の場合があります、MODIFYは書き込み中でまだ書いている途中の可能性があります。なのでファイルが完成しているCLOSE_WRITEとMOVED_TOで判断する必要があるのです。

inotifywaitを使って実装してみる

#!/bin/bash
cd /tmp/hotfolder
while [ 1 ]
do
HITFILE=`ls -1rt *.xml 2>; /dev/null | head -n 1`
if [ -z "${HITFILE}" ]
then
/usr/bin/inotifywait -qq -s -e CLOSE_WRITE,MOVED_TO /tmp/hotfolder -t 10
else
# ファイル検出時の処理
# 例として行数を表示して削除している
wc -l ${HITFILE}
rm ${HITFILE}
#
fi
done

最初のスクリプトのsleepの部分を置き換えてinotifywaitを使ってみました。/tmp/hotfolderにファイルの書き込みが終わるか、ファイルが移動やリネームされるのが終わるまで待ちますので。10秒のタイムラグはなくなります。-tで10を指定しているのはおまじないです。ずーっとまってしまうのが怖かったのでいったん10秒で抜けてファイルがあるかみています。 また最初にファイルの存在チェックしているのは、すでに格納されたファイルがあった場合に処理してから待たせるためです。しかし、このせいで起動直後、書き込み中のファイルを検出してしまうリスクはあります。

もう少しここは気を利かせる方法をまた考えます。

inotifywaitの使い方

コマンドのヘルプを一応コピーしておきます。

#inotifywait --help
inotifywait 3.14
Wait for a particular event on a file or set of files.
Usage: inotifywait [ options ] file1 [ file2 ] [ file3 ] [ ... ]
Options:
        -h|--help       Show this help text.
        @         Exclude the specified file from being watched.
        --exclude 
                        Exclude all events on files matching the
                        extended regular expression .
        --excludei 
                        Like --exclude but case insensitive.
        -m|--monitor    Keep listening for events forever.  Without
                        this option, inotifywait will exit after one
                        event is received.
        -d|--daemon     Same as --monitor, except run in the background
                        logging events to a file specified by --outfile.
                        Implies --syslog.
        -r|--recursive  Watch directories recursively.
        --fromfile 
                        Read files to watch from  or `-' for stdin.
        -o|--outfile 
                        Print events to  rather than stdout.
        -s|--syslog     Send errors to syslog rather than stderr.
        -q|--quiet      Print less (only print events).
        -qq             Print nothing (not even events).
        --format   Print using a specified printf-like format
                        string; read the man page for more details.
        --timefmt  strftime-compatible format string for use with
                        %T in --format string.
        -c|--csv        Print events in CSV format.
        -t|--timeout 
                        When listening for a single event, time out after
                        waiting for an event for  seconds.
                        If  is 0, inotifywait will never time out.
        -e|--event  [ -e|--event  ... ]
                Listen for specific event(s).  If omitted, all events are
                listened for.

Exit status:
        0  -  An event you asked to watch for was received.
        1  -  An event you did not ask to watch for was received
              (usually delete_self or unmount), or some error occurred.
        2  -  The --timeout option was given and no events occurred
              in the specified interval of time.

Events:
        access          file or directory contents were read
        modify          file or directory contents were written
        attrib          file or directory attributes changed
        close_write     file or directory closed, after being opened in
                        writeable mode
        close_nowrite   file or directory closed, after being opened in
                        read-only mode
        close           file or directory closed, regardless of read/write mode
        open            file or directory opened
        moved_to        file or directory moved to watched directory
        moved_from      file or directory moved from watched directory
        move            file or directory moved to or from watched directory
        create          file or directory created within watched directory
        delete          file or directory deleted within watched directory
        delete_self     file or directory was deleted
        unmount         file system containing file or directory unmounted

固定ページ: 1 2

 - Linux , , , , ,

  関連記事

no image
正規表現編集とテストを簡単に行える正規表現チェックツール

正規表現の編集やテストをさくさくやりたい その場にLinuxの環境でもあればse …

no image
[AjaXplorer]レンタルサーバのファイル管理

レンタルサーバのファイル管理するエクスプローラがほしい サーバにはレンタルサーバ …