Linuxでディレクトリの内容が変更されたときにスクリプトを自動的に実行する方法は?


17

新しいファイルが特定のディレクトリにコピーされるたびにスクリプトを自動的に実行したい。言い換えると、Linuxで変更のディレクトリを「監視」し、変更に応じて何かを実行する方法はありますか?


この議論は、すべてのstackexchangeサイトで開催されている。)を参照してくださいsuperuser.com/questions/181517/... stackoverflow.com/questions/4380527/...など
masterxilo

回答:


17

もしあなたが幸運にもdebianベースのディストリビューションにいるのなら、apt-get install dnotify。他のディストリビューションにもおそらく似たようなものがあります- dnotify名前を探してください。

dnotifyは、Linuxカーネル2.4.19+のdnotify APIに基づいたシンプルなプログラムです。dnotifyは、特定のディレクトリのコンテンツが変更されるたびに、指定されたコマンドを実行できます。コマンドラインから実行され、2つの引数を取ります。1つ以上の監視するディレクトリと、ディレクトリが変更されたときに実行するコマンドです。オプションは、どのイベントでトリガーするかを制御します:ファイルがディレクトリで読み取られたとき、ファイルが作成されたとき、削除されたときなど。

独自のプログラム内でこれを処理する場合、dnotifyも使用するAPIです。


4
@MikeB、グーグルがあなたに提案したことを示唆した後、私は代わりにinotifyを使用することになりました。正しい方向を教えてくれてありがとう。apt-get inotify-toolsのインストール
GeneQ 09

7
@ GeneQ、inotifyはdnotifyを置き換えました。
デビッド

1
Gentooでも同様:emerge inotify-tools
ジェームズスニーリンガー09

ええ、私は言ったつもりでした、カーネル2.4.19は一種の古代です;-) inotifyが行く方法です。
デビッドZ

そうそう...私はどちらが最近だったか忘れました:)
MikeyB 09

12

このようなinotify-toolsを使用してスクリプトを実行できます。変更されたファイル、新しいファイル、削除されたファイルの変更をディレクトリで監視し、スクリプトを実行します。

#!/bin/sh
while inotifywait -e modify -e create -e delete /home/me/code; do
    rsync [options] /home/me/code/ /media/nfs/code/ 
done

コピー中にソースディレクトリが変更された場合、inotifywaitはそれを認識せず、コピーが完了すると、さらに変更されるまでそれらの変更はコピーされないことを考慮してください。おそらく問題ではありません。
ラウルサリナスモンテアグード

デーモンモードでこれを実行するにはどうすればよいですか?
クリスF

4

incronは基本的にあなたが望むものです。通知メカニズムとしてinotifyを使用します(他の人が指摘しているように、dnotifyに優先します)が、inotifywaitなどを使用して継続的に実行するスクリプトは必要ありません(ただし、明らかに、cronデーモンは常に実行されています)。システム全体の「crontab」およびユーザー「crontab」は、標準のcronと同様の方法でサポートされますが、時間をトリガーとして指定するのではなく、inotifyイベントとファイル/ディレクトリ名が使用されます。

incronはUbuntuやDebianを含む多くのディストリビューション用にパッケージ化されていると思います。



0

entrは、私が見た中で最もシンプルで構成可能なファイル通知ツールです。その使用は、ディレクトリではなくファイルの監視に最適化されていますが、ケースを解決することもできます。

追加したファイルを検出して処理するには、などのその他のツールと組み合わせますmakeentr名前やそのようなものを送信するのではなく、実行するように指定したものを実行するだけです。

ディレクトリに追加されたファイルを確認するには:

## entr exits with rc=0 when terminated
## rc=1 when watched files go away or don't exist to begin with
## rc=2 when new files arrive in watched directories
until echo /path/to/directory_to_watch | entr -d do_stuff
do sleep 1; done

既存のファイルが変更されたときにも対応したい場合:

## Here's why it comes in handy that entr exits when new files are added --
## find gets re-run.
until find /path/to/directory_to_watch/ -path /path/to/directory_to_watch/* |
    entr -d do_stuff
do sleep 1; done

...そしてfind、ファイルが追加されると式が再び実行されるため、ループメカニズムが役立ちます。

より良いエラー処理が必要で、追加/削除されたファイルごとに1回だけ実行されるようにしたい場合、少し奇妙になりますが、これらの単純なケースでは素晴らしいです。


編集:incronのようなシステムレベルでこれを実行する場合は、スクリプトをお気に入りのプロセスマネージャーに追加するだけです(s6runitsystemdまたはsysvinitなど)、ループをスキップします。

#!/bin/bash
exec entr -d do_stuff < <(find /path/to/directory_to_watch/ -path /path/to/directory_to_watch/*)

execプロセス置換(<(...)プロセスマネージャから実行している場合)(すなわち道のシェルアウトを取得するために)適切にシグナリングを処理するために、重要です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.