変化を見張って動かす(inotifywait・systemd path)
定期実行は「時間が来たら動く」仕組みですが、世の中には「置かれた瞬間に処理したい」場面があります。1分ごとに見に行く cron では、最悪1分遅れます。そこで使うのが inotify、Linux カーネルが持つファイル監視の機構です。この回では inotifywait でファイルの出現を待ち受けるループの作り方と、同じことをサービスとして常駐させる systemd の path unit を学びます。何度も見に行くポーリングとの違いも押さえます。
cron や systemd timer は「時間が来たら動く」仕組みだ。多くの用途はこれで足りる。だが世の中には、時刻ではなく出来事に反応したい場面がある。「ファイルが置かれた、その瞬間に処理したい」というときだ。
たとえば、あるフォルダに画像が投げ込まれたら即座に変換したい。1分ごとに見に行く cron でも一応できるが、運が悪ければ最大1分待たされるし、何も来ない59分もフォルダを覗き続けることになる。無駄が多く、反応も鈍い。
🔔 カーネルが持つ監視機構 inotify
Linux には、ファイルの変化を見張るための仕組みがカーネルの中に用意されている。それが inotify(アイノーティファイ)だ。ファイルやフォルダに対する「作られた・書かれた・消された」といった出来事を、カーネルが検知して教えてくれる。
ここが肝心なのだが、inotify は自分でぐるぐる見に行くのではない。カーネルに「このフォルダを見張っておいて、何か起きたら起こして」と頼み、あとは眠って待つ。だから CPU をほとんど使わずに、変化の瞬間に反応できる。
⏳ inotifywait で待ち受ける
この inotify をコマンドラインから使えるようにしたのが inotifywait だ。監視したい場所と、拾いたい出来事の種類を渡すと、その出来事が起きるまでそこで待ち、起きたら一言返して終わる。
よく使うオプションは2つ。-e は拾う出来事の種類を指定する(create=作成、modify=変更、delete=削除など)。-m は monitor(モニター)モードで、1回で終わらず出来事のたびに何度でも報告し続ける。
-m で報告が流れ続け、while read でその1件ずつを受け取る。ファイルが置かれるたびに $file にその名前が入り、すぐ process.sh に渡せる。cron のような待ち時間はなく、置かれた瞬間に動く。
🛎️ サービスにするなら systemd path unit
手元のループは分かりやすいが、サーバーで常駐させるなら、端末を閉じたら止まってしまう while ループより、systemd に任せたほうが堅い。そのための仕組みが path unit(パスユニット)だ。
path unit は「指定した場所にファイルが現れたら、対応するサービスを起動する」という監視係を、systemd の一員として動かす。中身はやはり inotify なので、ポーリングではなく変化の瞬間に反応する。
PathExistsGlob は「この形のファイルが存在したら」という条件だ。相方の watch.service に実際の処理を書いておけば、条件が満たされた瞬間に systemd がそれを起動する。あとは systemctl enable --now watch.path で見張りが常駐する。
⚖️ ポーリングとの違いを押さえる
ここまでの主役はどれも、見に行くポーリングではなく、変化を通知してもらう監視だった。両者は結果が似て見えても、性質が違う。ポーリングは間隔ぶんだけ遅れ、空振りぶんだけ資源を使う。監視は即応で、待つ間は静かだ。
定期実行では届かなかった「その瞬間」に、これで手が届くようになった。inotifywait で待ち受け、常駐させたいなら systemd の path unit に任せる。時間で動く自動化と、出来事で動く自動化。この2枚のカードを場面で使い分けられれば、自動化の幅はぐっと広がる。