GNU/Linux >> Linux の 問題 >  >> Linux

ネットワークを介したLinuxでのファイル変更の監視に関する考え

Linuxでの変更についてディレクトリを監視することは、よく知られているメカニズムinotifyを介して可能です。 inotifyを使用すると、ディレクトリに監視を設定し、コンテンツのイベントを監視するように構成できます。何かが発生すると、ファイル記述子でメッセージを受信します。これは、ディレクトリがハードドライブ、SSD、USBドライブなどのローカルストレージにある場合は完全に機能しますが、ストレージが別のコンピューターにある場合、ディレクトリがネットワークファイルシステムにある場合は十分ではありません。同じまたは別のファイルシステムを介して接続された同じディレクトリで作業している別のユーザーがファイルを削除でき、そのファイルに設定したウォッチは通知されません。

これはなぜですか?

設計上、inotifyは操作(mkdirやchmodなど)の結果を取得しますが、監視がオンになっているファイルシステムの種類(ブラックボックス)は不明です(inotify)。ファイルシステムは監視が設定されていることを「認識」していないため、誰かがディレクトリを監視したいリモートホストに通知するなど、適切なアクションを実行できません。

あなたが唯一のユーザーである限り、問題はありません。監視したいディレクトリで作業しているユーザーが増えると、問題になります。

この振る舞いを公共図書館と比較することができます。あなたが唯一のユーザーである場合、どの本が利用可能で、どの本が借りていないかを知ることができます。あなただけがユーザーではなく、より多くのユーザーが本を借りている場合、これはもう不可能です。

その場合、図書館の誰かがユーザーが借りたものを管理する必要があり(これは通常のケースです)、本が利用可能かどうかを知るためにこの人に連絡する必要があります。これは、現在存在しない本が再び利用可能になったときに誰かに通知するように依頼するようなものです。

これで、ライブラリと連絡を取り、Linuxでは機能しないことを通知します。もちろん、ライブラリはリモートストレージであり、サーバーはライブラリで作業している「誰か」です。

Linuxでこれを機能させるには、時計が設定されていることをリモートサーバーに通知する必要があります。

実際、CIFSや最近のバージョンのNFSなどのファイルシステムには、サーバーへの時計の送信のサポートが含まれています。カーネル4.1.2のfs / cifs / cifssmb.cの6438行目のCIFSの場合、この(NT_TRANSACT_NOTIFY_CHANGE)のSMBメッセージはコメント化されています。しかし、まだ存在しています。これをコメントアウトする理由は、dnotifyで動作したためです。これは、長い間Linuxのデフォルトのfsnotifyシステムではありません。


Linuxでネットワークファイルシステムを使用して時計の転送を機能させると、カーネルスペースを介してFUSEが可能になります。

最近、私はこの「時計のサーバーへの転送」をFUSEで実装しようとしました。パッチを当てる必要がありました:

fsnotifyカーネルサブシステム。iノードでウォッチが設定または削除されたことをFUSEカーネルモジュールに通知します。

fsnotifyから通知された後にアクションを実行するFUSEカーネルモジュール。新しいオペコードを導入しました
FUSE_FSNOTIFYカーネルモジュールがinodenumberとマスクとともにユーザースペースデーモンに送信します。

ユーザースペースファイルシステムの適切な関数を呼び出してFUSE_FSNOTIFY呼び出しを受信して​​処理するFUSEライブラリ。

fsイベントを受信して​​処理し、それらをVFSに報告するためのFUSEライブラリ。

動作を詳しく見てみると、ウォッチがバックエンドのユーザースペースファイルシステムによって正常に設定されている場合(ENOSYSに応答することも可能であることに注意してください)、バックエンドはいつでもウォッチにイベントを送信できます。時計が削除されます。このイベントをどうするか?

考えられるシナリオ:

追加のFUSEオペコードFUSE_FSNOTIFY_EVENTを導入し、バックエンドプロトコルから受信したイベントのマスクを、fsnotifyが理解できるものに変換し、新しいオペコード、時計のiノード、エントリの名前、およびを使用してFUSEモジュールに送り返します。翻訳されたマスク。彼の番のFUSEモジュールは、それをfsnotifyサブシステムに送信します。fsnotifyサブシステムは、イベントがバックエンドにあるという情報が提供されるリストナー(inotifyまたはfanotify)に通知します。 (たとえば、FAN_REMOTEをfanotifyするために、イベントマスクIN_REMOTEをinotifyする場合は、追加のイベントフラグが必要です)。この情報をどう処理するかはリスナー次第です。ローカルVFSは、すでに最新である場合とそうでない場合があります。

注:

マスクをバックエンドからfsnotifyが理解できるものに変換することは、イベントによっては非常に簡単な場合とそうでない場合があります。監視対象ディレクトリ内のエントリの作成(または削除)などの基本的なイベントは単純であり(FS_CREATEおよびFS_DELETEそれぞれ)、所有者の変更もそれほど難しくありません(FS_ATTRIB)が、拡張属性のようなものです(SMBはそれらの多く)は、FS_ATTRIBとして一般的なものにのみ変換できます。

FUSEモジュールは、時計やiノードがまだ有効であるかどうか、および時計のマスクがイベントマスクに適用されているかどうかを確認する必要があります。

追加のマスクビットIN_REMOTE(inotify用)およびFAN_REMOTE(fanotify用)が必要です。

二重の情報は避けなければなりません。これは注意が必要です。たとえば、ウォッチがオンになっているのと同じホスト上のウォッチされたディレクトリにファイルを作成します。この操作が成功すると、fsnotifyイベントFS_CREATEが発生し、FS_CREATE|も作成されます。 FS_REMOTEイベント。操作がバックエンドで正常に実行されたため、このメッセージが表示されます(バックエンド→ヒューズライブラリ→FUSEカーネルモジュール→fsnotifyサブシステム→inotifyおよび/またはfanotifyから)。

これに取り組む1つの方法は、他の人が開始したイベントのみを送信するようにバックエンドに依頼することです。バックエンドの場合、FSイベントのイニシエーター(ホスト)を接続を確立しているホストと比較するのは非常に簡単です。

別の解決策は、報告されたイベントをヒューズライブラリおよびFUSEモジュールのローカルキャッシュと比較することです。ファイルを作成する例では、ライブラリ(およびFUSEモジュール)は、エントリが監視対象ディレクトリにすでに存在することを確認する必要があります。そうでない場合は、このホストによって開始されません。削除の場合、これは同様です。

ファイルの書き込みや所有者の変更などの他のイベントの場合、この方法では不十分です。リモートで変更された内容(新しいサイズ、新しい所有者など)に関する追加情報は、リモートホストから送信されるメッセージに含める必要があります。

その情報がバックエンドによって提供されない場合、別の解決策は、クライアントに代わってFSイベントの監視をデーモンに任せて、最近のローカルイベントのキャッシュを維持することです。リモートイベントが報告され、キャッシュ内に同等のローカルイベントが見つからない場合、別のホストによって開始されます。これは、特定のユーザーの接続を使用してイベントが報告されるため、注意が必要になる場合があります。他のユーザーは、イベントの受信を許可されている場合とされていない場合があります。そして、このキャッシュはどのくらいの大きさになりますか?

上記でFUSEを使用しましたが、CIFSやNFSなどの他のファイルシステムでも同様だと思います。

そうです、さらに別のオプションがあります。5秒ごとにポーリングするだけです。

ステフボン


Linux
  1. Linuxのwatchコマンドでコマンドとタスクを監視する

  2. findコマンドを使用してLinux上のファイルとディレクトリを検索します

  3. statコマンドを使用してLinuxのファイルステータスを確認します

  1. Linuxtacコマンドの使用を開始する

  2. xclipを使用してLinuxコマンドラインでコピーして貼り付けます

  3. Linuxコンテナの舞台裏

  1. chageコマンドを使用してLinuxシステムのパスワードを強制的に変更する

  2. ファイル変更の監視 c++ linux

  3. Linux のコマンド ライン ツールを使用してマイク レベルを監視する