ファイルシステム変更イベント
Netatalkには、afpdプロセスが特定のAFPセッションやファイルシステムの動作を報告できるようにする、ファイルシステム変更イベント(FCE)メカニズムが組み込まれている。
発生した FCE イベントを捕捉する方法は二つある:
- UDP 経由で FCE パケットを一つ以上のリスナーアプリケーションに送信する
- 発生したイベントごとにローカル通知スクリプトを実行する
二つの方法は独立している。サーバーはどちらか一方、あるいは両方を同時に使用することができる。
FCE サポートはビルド時に有効化されていなければならない。Meson オプションは -Dwith-fce=true であり、デフォルトで有効になっている。
イベント
以下の FCE イベント名は fce events オプションで使用される:
- ファイル変更 (fmod)
- ファイル削除 (fdel)
- ディレクトリ削除 (ddel)
- ファイル作成 (fcre)
- ディレクトリ作成 (dcre)
- ファイル移動または名前変更 (fmov)
- ディレクトリ移動または名前変更 (dmov)
- ユーザーログイン (login)
- ユーザーログアウト (logout)
FCE プロトコルバージョン 1 は基本的なファイルおよびディレクトリイベントをサポートする:
- fmod
- fdel
- ddel
- fcre
- dcre
FCE プロトコルバージョン 2 はプロセス ID やユーザー名などのイベントメタデータを追加し、移動、ログイン、およびログアウトイベントに必要である:
- fmov
- dmov
- login
- logout
新しい展開では、fce version = 2 を使用する。
UDP でイベントを捕捉する
fce listener オプションは、FCE イベントを UDP データグラムとしてホストとオプションのポートに送信する:
[Global]
fce listener = localhost:12250
fce version = 2
fce events = fmod,fdel,ddel,fcre,dcre,fmov,dmov,login,logout
ポートが指定されていない場合、Netatalk はポート 12250 を使用する。複数のリスナーは、fce listener を複数回追加することで設定できる。
Netatalk には、テストに使用できるシンプルなリスナーアプリケーション fce_listen が含まれている:
$ fce_listen -h localhost -p 12250
Listening for Netatalk FCE datagrams on localhost:12250...
FCE Start
ID: 1, Event: FCE_LOGIN, pid: 429924, user: myuser, Path:
ID: 2, Event: FCE_FILE_CREATE, pid: 429924, user: myuser, Path: /srv/afp/untitled folder
ID: 3, Event: FCE_DIR_MOVE, pid: 429924, user: myuser, source: /srv/afp/untitled folder, Path: /srv/afp/My Folder
UDP 配信は、外部インデクサー、監査コレクター、または afpd によって実行されることなくイベントを受信する必要がある他のプログラムに便利である。UDP は信頼性がないため、受信者は FCE イベント ID を使用して欠落したパケットを検出する必要がある。
ファイルシステムのアクティビティのバーストがパケット損失を引き起こす場合、fce sendwait は発生した UDP イベントの間に小さな遅延を追加できる:
[Global]
fce listener = localhost:12250
fce sendwait = 10
値はミリ秒単位で、0 から 999 の間でなければならない。
スクリプトでイベントを捕捉する
fce notify script オプションは、発生した FCE イベントごとにローカルスクリプトを実行する:
[Global]
fce notify script = /usr/local/libexec/netatalk/fce_ev_script
fce version = 2
fce events = fmod,fdel,ddel,fcre,dcre,fmov,dmov,login,logout
スクリプトメソッドは fce listener を必要としない。単独で使用することも、UDP リスナーと一緒に使用することもできる。
Netatalk はスクリプトをバックグラウンドで /bin/sh -c を通して実行する。設定されたスクリプトパスの後に、イベントを説明するコマンドラインオプションが続く。例えば:
running /usr/local/libexec/netatalk/fce_ev_script -v 2 -e FCE_FILE_CREATE -i 2 -P '/srv/afp/Example File' -p 60246 -u 'myuser' as user 503
スクリプトに渡されるオプションは以下の通り:
- -v VERSION: FCE スクリプト引数バージョン
- -e EVENT: イベント名、例えば FCE_FILE_CREATE
- -i ID: イベント ID
- -P PATH: イベントパス、イベントにパスがある場合
- -S SOURCE: 移動または名前変更イベントのソースパス
- -p PID: afpd プロセス ID
- -u USER: AFP セッションユーザー
-p および -u オプションは fce version = 2 で使用可能である。
インストールされた fce_ev_script ヘルパーはこれらのオプションを受け入れ、タグ netatalk-fce で syslog に人間が読めるイベント行を書き込む。ソーススクリプトは contrib/scripts/fce_ev_script.sh として管理されている。
出力の例:
FCE Event: FCE_FILE_MOVE, protocol: 2, ID: 4, pid: 429924, user: myuser, source: /srv/afp/old.txt, path: /srv/afp/new.txt
スクリプト実行環境
通知スクリプトは AFP セッションユーザーとして実行され、必ずしも root または Netatalk を開始したユーザーとして実行されるわけではない。
いくつかの実際的な結果がある:
- スクリプトパスは AFP セッションユーザーによって実行可能でなければならない
- スクリプトパス内のすべての親ディレクトリは、そのユーザーによって検索可能でなければならない
- スクリプトによって書き込まれたファイルは、そのユーザーによって書き込み可能でなければならない
- 相対パスは避けるべきである。なぜなら、ヘルパーはコマンドを実行する前に / にディレクトリを変更するからである
ビルドシステムは、ヘルパーを Netatalk の libexec ディレクトリの下にインストールする。/usr/local/libexec をインストール用に設定された libexec ディレクトリに置き換える。afpd をそのインストール済みパスで設定する:
[Global]
fce notify script = /usr/local/libexec/netatalk/fce_ev_script
診断用のファイルログを取得するために、ヘルパーをラップして NETATALK_FCE_LOG_FILE を設定する:
#!/bin/sh
NETATALK_FCE_LOG_FILE=/tmp/fce.log
export NETATALK_FCE_LOG_FILE
exec /usr/local/libexec/netatalk/fce_ev_script "$@"
ファイルログが有効になっているが /tmp/fce.log が更新されない場合は、ログファイルの所有者とモードを確認する。
イベントのフィルタリングと集約
fce events オプションは、どのイベントが発生するかを制御する:
[Global]
fce events = fcre,dcre,fmov,dmov
fce ignore names オプションは、選択されたファイル名のイベントを抑制する。デフォルトで無視される名前は .DS_Store である。
[Global]
fce ignore names = .DS_Store,Thumbs.db
fce ignore directories オプションは、選択された絶対ディレクトリパスの下のイベントを抑制する。パスはスラッシュで終わってはいけない。
[Global]
fce ignore directories = /srv/afp/cache,/srv/afp/tmp
fce coalesce オプションは、騒々しい作成および削除イベントのバーストを減らすことができる:
[Global]
fce coalesce = all
ファイル変更イベントは fce holdfmod によって遅延され、デフォルトでは 60 秒である。スクリプトの即時テストのために、0 に設定する:
[Global]
fce holdfmod = 0