開発室ブログ

Inotify Linux WinSCP

WinSCP のミラーリング機能 & inotify-tools(inotifywait)でファイル・ディレクトリを監視する

開発室の阿部です。

先日、会社まで地下鉄1本でいけるところに引っ越しました。 最初は駅徒歩5分くらいで~、ロードヒーティング付きで~、築浅で~なんて思いながら家探しをしてましたが、結局駅徒歩15分でまぁまぁ古い家になるという。 理由としては、めちゃくちゃ広くて、ベランダが謎に2つ有ることに感動してしまい、即決してしまいましたが、結局2つも活用しないんですよね。しかもカーテン代が高く付く始末。

不動産の人は「めっちゃ風通るので夏でも涼しいですよ~」なんていわれました、が、暑い。 もう死ぬかと。 そもそも住んでないのに涼しいかなんて分からないだろと。

それと風呂の水圧。 住む家は水圧がしっかりと有るところ!なんて思い相談してみましたが 「基本水圧はどこも有る程度あるので大丈夫ですよ~」なーんていわれて普通に信じましたが、いざ住むとなんだこれ!!!!っていうぐらい弱いです。 水圧が高く感じるシャワーヘッドとか買いましたが、それでもめちゃくちゃ弱いです。直で眼球に当てても平気です。 大家に聞くと、オール電化の貯蓄型の温水器は弱くなってしまうと。他の住民からもなんぼか言われたことが有ると。

と、こんな具合に文句言いつつも近くにコンビニがあったり、駐車場が屋根つきだったりとプラスなこともあるので、目をつぶって住もうと思います。 今度は駅徒歩5分、築浅、都市ガス、ロードヒーティングと、理想の家にありつけるようガンバリマス。

本題

いま、社内のPCで使ってるソフトで定期的にデータを測定し、それが完了したらエクスポートして、レポートサイトにアップロードする。という作業を自動化できないという相談がありましたので 今回はFTPクライアントのWinSCP と Linux2.6から追加されたinotifyを使って自動アップロード(WinSCP)+自動インポート(inotify)を構築しました。

WinSCPでのファイル監視 – ミラーリング機能

FTPクライアントのWinSCPは”ミラーリング機能”が付いていて、特定のディレクトリとリモートディレクトリを常に同期してくれます。 今回これを利用するのですが、アプリケーションを立ち上げての起動ではなく、windowsのバッチファイルから起動できるようにし、それをスタートアップに入れることで 万が一ローカルPCが再起動された場合、自動でミラーリングが始まるようにしました。

流れとしてはWinSCPにはコンソール機能が存在します。 バッチファイルからコンソール機能を実行するには以下のようにします。

"C:\Program Files (x86)\WinSCP\WinSCP.com" SessionName /console /script=.\SCP.scr

ここで注意なのが、WinSCP.exeでは無くWinSCP.comです。 /consoleでコンソール機能を指定し、/scriptで起動後に実行するコマンドをまとめたファイルを指定します。

SessionName で予めアプリケーション側で保存して有るセッション名を指定することで、スクリプトに接続情報を書かなくて済みます。

必要な情報を入力し、保存すると

ここでセッション名を保存することが出来ます。デフォルトはユーザ名@接続先になりますが、分かりやすい名前に変更可能です。 このセッション名をSessionNameに入れてください。

ミラーリング機能は keepuptodate

次にスクリプトにミラーリング機能を実行するコマンドを入力します

keepuptodate "監視対象のディレクトリ" "同期先のリモート先ディレクトリ"

これで監視対象のディレクトリに変更があった場合、リモートに自動的にアップロードされます。リモート先にファイルが存在していた場合、強制的に上書きされます。

Inotifywait でファイル・ディレクトリ監視

ローカル -> リモート の準備は出来たので次はリモート側でファイルがアップロードされた時に、検知しデータベースにインポートするようにします。

inotifyの導入方法についてはこちらを参考にしました。

inotify-toolsでファイルやディレクトリを監視する

WinSCP から送信されたファイルに謎の拡張子が (.filepart)

WinSCPから送信されたファイルをinotify(inotifywait)の読み込むとイベントによってはファイル名に .filepart という拡張子が付くことがあります。 これはWinSCPの仕様で、ファイルが送信し終わった際にこの拡張子は削除されます。

当初、「CLOSE_WRITE」でイベントを検知してましたが、.filepartが付くので 「ATTRIB」で検知したところ.filepartの無いファイル名が取得できました。

バックグラウンドでの実行を予定していたので、シェルにまとめるとこんな感じです。

#!/bin/bash

trap "exit 0" 3

inotifywait -e ATTRIB -m -r 監視ディレクトリ --format "%w%f" |

while read FILE; do
    if [[ $FILE =~ .*csv$ ]]; then
        /usr/bin/php $(dirname $FILE)/../import.php $FILE
    fi
done

「%w%f」でアップロードされたファイルのフルパスを取得しています。 イベントを検知した後は、拡張子の判定を行い、真であれば、インポート用のphpを実行しています。

あとは、サービスでこのシェルをバックグラウンドで実行すれば、完了となります。

あまりこのような環境が必要になることはありませんが、部分的に今後活用できたらな~と思います。

RecentPost