※当サイトの記事には、広告・プロモーションが含まれます。

Linuxの標準の機能でファイルの変更を検知したかったんだが...

www.itmedia.co.jp

 米ミシガン大学、米コロンビア大学、米Microsoft南カリフォルニア大学に所属する研究者らが発表した論文「Reviving Dead Links on the Web with Fable」は、訪れたWebサイドから404エラーを検出して新しいURLを提供する自動システムを提案した研究報告である。

404エラーが出ても“生きたURL”を特定してくれるアドオン 米Microsoftの研究者らが開発:Innovative Tech - ITmedia NEWS

 Webサイトを訪れる際に「Error 404 - Page Not Found」(404エラー - ページが見つかりません)というメッセージを目にする経験は、多くの人にとってなじみ深いものであろう。このようなメッセージは、特定のリンク先のページが存在しない、削除されている、またはページのURLが変更されている場合に表示される。

404エラーが出ても“生きたURL”を特定してくれるアドオン 米Microsoftの研究者らが開発:Innovative Tech - ITmedia NEWS

 この研究では、無効なリンクを自動的に処理するシステム「FABLE」を提案する。FABLEは、壊れたリンクの検出だけでなく、同じサイト内で他のページの旧URLが新しいURLにどのように変わったかのパターンを学習し、それを活用して、該当ページの新しいURLを探索する。

404エラーが出ても“生きたURL”を特定してくれるアドオン 米Microsoftの研究者らが開発:Innovative Tech - ITmedia NEWS

 評価実験では、Wikipedia、Stack Overflow、Mediumの50万近いページを調べ、無効なリンクを見つけ、FABLEで2万を処理した。その結果、リンクの約4分の1が新しいURLであり、約90%が正しいページにリンクしていることが判明した。

404エラーが出ても“生きたURL”を特定してくれるアドオン 米Microsoftの研究者らが開発:Innovative Tech - ITmedia NEWS

⇧ 待望の機能ですが、評価実験のように範囲を限定するのではなく、実際の制限の無い環境での精度が気になるところですな。

Linuxの標準の機能でファイルの変更を検知したかったんだが...

シェルスクリプトの動作確認で、ファイルが更新されるケースについて、テストを自動化できないかと思って、ネットで情報を漁っていたら、

www.nminoru.jp

qiita.com

⇧ 上記サイト様によりますと、「inotify」と「fanotify」いうものが用意されているらしいですと。

まず、「inotify」について、Wikipediaさんによりますと、

inotify (inode notify) とは、ファイルシステムへの変更を通知するようファイルシステムを拡張して、その変更をアプリケーションに報告するLinuxカーネルサブシステムである。inotifyに先行して存在し、類似の目標を持つdnotify英語版は、inotifyに取って代わられている。

inotify - Wikipedia

inotifyはJohn McCutchanが作成し、2005年8月29日にリリースされたLinuxカーネルのバージョン2.6.13で、inotifyはLinuxカーネルメインラインにマージされた。以降のバージョンのLinuxカーネルでは、inotifyはさらに改良されている。GNU Cライブラリ (glibc) では、inotifyに必要なライブラリインタフェースは2006年3月にリリースされたバージョン2.4で追加され、2006年9月にリリースされたバージョン2.5でinotifyを完全にサポートした

inotify - Wikipedia

⇧ 2006年9月時点で、Linuxの標準の機能になったという位置付けらしい。

用途はと言うと、

inotifyの主な用途の1つとしては、Beagleなどのデスクトップ検索ユーティリティが挙げられる。inotifyの機能により、数分おきにファイルシステム変更をスキャンするといった非常に効率が悪い作業をせずに、変更されたファイルの再インデックス化英語版が可能となる。

inotify - Wikipedia

inotifyは、ディレクトリビューの自動更新、設定ファイルの再読み込み、ログの変更、バックアップ同期アップロードなどにも使える。

inotify - Wikipedia

⇧ なるほど、リアルタイムな検知ができるってことですかな。

ただ、良い面ばかりと言うわけもなく、

制限

inotifyにより課される制限は以下の通りである:

  • inotifyは再帰的なディレクトリ監視をサポートしていない。このため、inotifyによる監視はサブディレクトリ毎に個別に行う必要がある
  • inotifyは、sysfsprocfsによるイベントは一部しか報告しない。
  • inotify経由の通知は、直近に発生したファイルシステムのイベントをカーネルが全て認識していることが前提となっているが、NFSなどのネットワーク接続されたファイルシステムに対してそれが常にできているとは限らない。NFSなどはあるクライアントによる変更をすぐには他のクライアントへブロードキャストしないからである。
  • inotifyは改名されたイベントを直接処理しない。つまりinotifyは改名前と改名後のそれぞれにおける2つのイベントを発行する。どの順序でイベントが通知されても良いように、イベントの内容を吟味・照合する必要がある。

inotify - Wikipedia

⇧ なかなか、痒いところに手が届かない感じではありますと。

そして、標準の機能であるしいのだけど、

github.com

inotify-tools is a C library and a set of command-line programs providing a simple interface to inotify.

https://github.com/inotify-tools/inotify-tools

⇧ だいたい、「inotify-tools」ってライブラリを導入して「inotify」を利用していく感じになるらしい。

ライブラリをインストールする必要があることから、実質、Linuxの標準の機能のみで利用はできないってことですな...

で、

ogasanet.com

⇧ 上記サイト様によりますと、「inotify-tools」で用意されているイベントが曲者らしい。

というか、検知とかの用途の場合、「inotify」より「inotifywait」の方を使う感じになるんかね?

「inotifywait」のマニュアルのページによると、

man7.org

EVENTS         top

       The following events are valid for use with the -e option:

       access A watched file or a file within a watched directory was
              read from.

       modify A watched file or a file within a watched directory was
              written to.

       attrib The metadata of a watched file or a file within a watched
              directory was modified.  This includes timestamps, file
              permissions, extended attributes etc.

       close_write
              A watched file or a file within a watched directory was
              closed, after being opened in writable mode.  This does
              not necessarily imply the file was written to.

       close_nowrite
              A watched file or a file within a watched directory was
              closed, after being opened in read-only mode.

       close  A watched file or a file within a watched directory was
              closed, regardless of how it was opened.  Note that this
              is actually implemented simply by listening for both
              close_write and close_nowrite, hence all close events
              received will be output as one of these, not CLOSE.

       open   A watched file or a file within a watched directory was
              opened.

       moved_to
              A file or directory was moved into a watched directory.
              This event occurs even if the file is simply moved from
              and to the same directory.

       moved_from
              A file or directory was moved from a watched directory.
              This event occurs even if the file is simply moved from
              and to the same directory.

       move   A file or directory was moved from or to a watched
              directory.  Note that this is actually implemented simply
              by listening for both moved_to and moved_from, hence all
              move events received will be output as one or both of
              these, not MOVE.

       move_self
              A watched file or directory was moved. After this event,
              the file or directory is no longer being watched.

       create A file or directory was created within a watched
              directory.

       delete A file or directory within a watched directory was
              deleted.

       delete_self
              A watched file or directory was deleted.  After this event
              the file or directory is no longer being watched.  Note
              that this event can occur even if it is not explicitly
              being listened for.

       unmount
              The filesystem on which a watched file or directory
              resides was unmounted.  After this event the file or
              directory is no longer being watched.  Note that this
              event can occur even if it is not explicitly being
              listened to.

https://man7.org/linux/man-pages/man1/inotifywait.1.html

⇧ イベントとしては、全部で15個用意されてるらしい。

No. イベント名 内容
1 access 監視対象のファイルまたはディレクトリ内のファイルが読まれた
2 modify 監視対象のファイルまたはディレクトリ内のファイルが更新された
3 attrib 監視対象のファイルまたはディレクトリ内のファイルのメタデータが更新された
4 close_write 監視対象のファイルまたはディレクトリ内のファイルが書き込み可能で開かれた後、閉じられた
5 close_nowrite 監視対象のファイルまたはディレクトリ内のファイルが読み取り専用で開かれた後、閉じられた
6 close close_writeまたはclose_nowrite含む、全ての閉じる系
7 open 監視対象のファイルまたはディレクトリ内のファイルが開いた
8 moved_to 監視対象のディレクトリにファイルまたはディレクトリが移動した
9 moved_from 監視対象のディレクトリからファイルまたはディレクトリが移動された
10 move moved_toまたはmoved_from含む、移動系
11 move_self 監視対象のファイルまたはディレクトリ自体が移動。監視対象でなくなる
12 create 監視対象のディレクトリ内にファイルまたはディレクトリが作成された
13 delete 監視対象のディレクトリ内にファイルまたはディレクトリが削除された
14 delete_self 監視対象のファイルまたはディレクトリ自体が削除。監視対象でなくなる
15 unmount 監視対象のファイルまたはディレクトリ自体がアンマウント。監視対象でなくなる

となるようなのだけど、「inotify」のマニュアルのページによると、

man7.org

イベントとしては、

  1. IN_ACCESS (+)
  2. IN_ATTRIB (*)
  3. IN_CLOSE_WRITE (+)
  4. IN_CLOSE_NOWRITE (*)
  5. IN_CREATE (+)
  6. IN_DELETE (+)
  7. IN_DELETE_SELF
  8. IN_MODIFY (+)
  9. IN_MOVE_SELF
  10. IN_MOVED_FROM (+)
  11. IN_MOVED_TO (+)
  12. IN_OPEN (*)
  13. IN_MOVE
  14. IN_CLOSE
  15. IN_DONT_FOLLOW (since Linux 2.6.15)
  16. IN_EXCL_UNLINK (since Linux 2.6.36)
  17. IN_MASK_ADD
  18. IN_ONESHOT
  19. IN_ONLYDIR (since Linux 2.6.15)
  20. IN_MASK_CREATE (since Linux 4.18)
  21. IN_IGNORED
  22. IN_ISDIR
  23. IN_Q_OVERFLOW
  24. IN_UNMOUNT

⇧ 24個あるらしく、数が一致しないんだが...

「inotify」と「inotifywait」の違いが分からん...

Web界隈のセキュリティ分野の第一人者でもあられる徳丸氏が公開してる情報によりますと、

blog.tokumaru.org

私自身としても、サイトに侵入されてしまうかもしれないという想定は心情的には受け入れにくいものではありますが、冷静に考えれば侵入されるという事態はあり得るわけで、仮に侵入された場合に素早く対処できる施策を施しておきたいと考えるようになりました。と言っても、何分にも個人経営のサイトですので、掛けられる予算も限られています。そこで、無償で利用できる改ざん検知ツールについて検討しました。
検討したツールは以下の通りです。

実際には両方を導入して運用していますが、本稿ではinotifywaitについて報告します。

多発するWeb改ざんに備えてinotifywaitによる改ざん検知を導入した | 徳丸浩の日記

inotify(inotifywait)はリアルタイムに上記の表示が得られます。一方、オープンソース版のTripwireは定期的なバッチ処理による監視なので、リアルタイム性はありません。

多発するWeb改ざんに備えてinotifywaitによる改ざん検知を導入した | 徳丸浩の日記

⇧ とあり、「inotify」と「inotifywait」の違いについては、特に言及されてはおられない。

引き続き、ネットの情報を漁っていたところ、

unix.stackexchange.com

I need to monitor a directory and do some post actions based on the events happened. I am familiar with inotifywait but since we use docker based on alpine, I was thinking about is there other way to do that.

https://unix.stackexchange.com/questions/656506/how-is-inotifyd-different-from-inotifywait-in-term-of-monitoring-a-directory-and

Then I found Inotifyd, according to the document there said "While there are tools designed around inotify (inotify-tools) alpine has a build in tool called inotifyd (part of busybox) to execute a command on file system events."

https://unix.stackexchange.com/questions/656506/how-is-inotifyd-different-from-inotifywait-in-term-of-monitoring-a-directory-and

⇧ 何やら、「Inotifyd」なるものも存在するそうな。

wiki.alpinelinux.org

Inotifyd

Sometimes we need to monitor a directory (or file) and do some post processing/actions. Instead of polling the directory for changes we can use inotify to watch a specific folder or file and be notified if something happens within its context. While there are tools in aports designed around inotify (inotify-tools) alpine has a build in tool called inotifyd (part of busybox) to execute a command on file system events. Below is an example of how you can setup a watch folder with just base alpine (busybox and openrc).

https://wiki.alpinelinux.org/wiki/Inotifyd

⇧ なるほど、「Alpine Linux」では、「Inotifyd」というものが用意されているらしい。

う~む、なかなかにカオス...

一旦、「inotify」の調査を切り上げて、「Fanotify」の方も調べてみたところ、

www.linux-magazine.com

Fanotify

Fanotify is such an API. It made a debut in Linux 2.6.36, almost five years after inotify. Conceptually, fanotify is similar to inotify, yet somewhat closer to the low-level kernel API they both use. It introduces a set of system calls to obtain a file descriptor and "marks" filesystem objects as being watched. Unlike inotify, fanotify can monitor a mounted filesystem as a whole. Monitoring a single directory recursively is still impossible, though. Whereas the inotify file descriptor is read-only, its fanotify counterpart is writable, which is how you tell fanotify your access permission decisions.

https://www.linux-magazine.com/Issues/2017/194/Core-Technologies

⇧ という情報があって、マウントされたファイルシステム全体の監視はできるけど、1つのディレクトリを再帰的に監視することはできない、ってのが意味がよく分からんのだけど…

Wikipediaさんの「Linux Kernel interfaces」の説明によると、

The Linux kernel provides multiple interfaces to user-space applications that are used for varying purposes and that have varying properties by design. There are two types of application programming interface (API) in the Linux kernel

  1. the "kernel–user space" API; and
  2. the "kernel internal" API.

https://en.wikipedia.org/wiki/Linux_kernel_interfaces

Additions to POSIX

As in other Unix-like systems, additional capabilities of the Linux kernel exist that are not part of POSIX:

DRM has been paramount for the development and implementations of well-defined and performant free and open-source graphics device drivers without which no rendering acceleration would be available at all, only the 2D drivers would be available in the X.Org Server. DRM was developed for Linux, and since has been ported to other operating systems as well.

https://en.wikipedia.org/wiki/Linux_kernel_interfaces

Linux Kernelの専用の機能だったのが、「POSIX」に追加されたということらしい。

POSIX」はと言うと、

linuc.org

POSIX (Portable Operating System Interface) は、UNIX 系 OS 間でアプリケーションの移植性を高めるために定義された IEEE の標準規格です。簡単に言うと「OS の互換性のための標準規格」です。

POSIX - Linux技術者認定 LinuC | LPI-Japan

POSIX(ポジックスPortable Operating System Interface)は、オペレーティングシステム (OS) の標準的なインタフェースおよび環境を定義するIEEE規格であるソースコードレベルでの移植性の高いアプリケーションソフトウェアの開発を容易にすることを目的として、主にUNIX系のOSに関して、各OSが共通して持つべきコマンドラインインタプリタ(シェル)、共通のユーティリティプログラム、およびアプリケーションプログラミングインタフェース (API) について定めている

POSIX - Wikipedia

POSIX仕様に準拠したソースコードは、POSIX準拠OSであればどれでも動作させることができる。アプリケーション開発者とシステム実装者の両方から利用されることを意図している。

POSIX - Wikipedia

⇧ とありますと。

POSIX準拠」については、

qiita.com

POSIX とは OS ベンダーとアプリケーション開発者の両方が参照すべきドキュメントです。そのため POSIX 準拠の要件にも「OS ベンダー向け」と「アプリケーション開発者向け」の二つの要件が定義されています。これらが定義されている場所は 2. Conformance です。

POSIX準拠とは本当はどういうことなのか?「POSIXで規定されたものだけを使う」ではありません #ShellScript - Qiita

アプリケーション開発者向けの POSIX 準拠の定義は大きく五種類ありますが、その中で私が考える二つの大きな定義は「厳密な POSIX 準拠アプリケーション」と「拡張機能を利用する POSIX 準拠アプリケーション」です。以下はこの二つの違いを示したものです。

POSIX準拠とは本当はどういうことなのか?「POSIXで規定されたものだけを使う」ではありません #ShellScript - Qiita

⇧ 上記サイト様がまとめて下さっています。

なるほど、「POSIX準拠」が複雑なことと、

『The system calls futex (fast userspace mutex), epollsplicednotifyfanotify, and inotify have been exclusive to the Linux kernel so far.』

と、POSIXに追加されてるからといって(POSIX準拠であると仮定)、どこでも動くかと言うと、そんなことは無いってことなんですかね。

と言うのも、

github.com

fsnotify is a Go library to provide cross-platform filesystem notifications on Windows, Linux, macOS, BSD, and illumos.

https://github.com/fsnotify/fsnotify

クロスプラットフォームを考慮したツールを作成してらっしゃる方がおられるようなので。

で、fsnotifyにインスパイアされた方が、

github.com

Cross-platform filesystem notification library for Rust.

https://github.com/notify-rs/notify

Origins

Inspired by Go's fsnotify and Node.js's Chokidar, born out of need for cargo watch, and general frustration at the non-existence of C/Rust cross-platform notify libraries.

https://github.com/notify-rs/notify

⇧ Rustでライブラリを作っていらっしゃるようです。

まぁ、いろいろ、調べて分かったことは、Linuxの標準の機能だけではファイル検知の仕組みを構築するのは厳しそうで、何かしらのライブラリを導入するしか無さそうってことですな。

う~む、どうしたもんか、一応「cron」で

thoames.hatenadiary.jp

vividcode.hatenablog.com

qiita.com

⇧ 複数ファイルを使うことができるらしいので、テスト用の「cron」設定をするという手段が取れるかもしれませんと。

ちなみに、「cron」のような機能に関連する話で、「Rundeck」というOSSOpen Source Software)なライブラリがあるらしく、

tech-blog.monotaro.com

www.rivercrane.com

⇧ 管理しなければいけない「cron」の数が多くなってきた場合に、一元管理ができるというメリットがあるようです。

デメリットもあるようですが。

ちなみに、「cron」と「inotify」をフュージョンさせた感じなのか、

blog.glidenote.com

www.itmedia.co.jp

inotify.aiken.cz

incron :: inotify cron system

This program is an "inotify cron" system. It consists of a daemon and a table manipulator. You can use it a similar way as the regular cron. The difference is that the inotify cron handles filesystem events rather than time periods.

https://github.com/notify-rs/notify

⇧「incron(inotify cron)」なるライブラリも存在するそうな。

とりあえずは、ライブラリとかのインストール不要で、Linuxの標準の機能で実現できる「cron」でテスト用のスクリプトが組めないか、模索してみますかね...

毎度モヤモヤ感が半端ない...

今回はこのへんで。