How to Monitor a Complete Directory Tree for Changes in Linux

How to monitor a complete directory tree for changes in Linux?

To my knowledge, there's no other way than recursively setting an inotify watch on each directory.

That said, you won't run out of file descriptors because inotify does not have to reserve an fd to watch a file or a directory (its predecessor, dnotify, did suffer from this limitation). inotify uses "watch descriptors" instead.

According to the documentation for inotifywatch, the default limit is 8192 watch descriptors, and you can increase it by writing the new value to /proc/sys/fs/inotify/max_user_watches.

monitor a folder tree for changes and run a script when a file is created - linux

inotify is being around for a while, It's stable and is part of main stream of many distros.

How to install:

on Ubuntu:

sudo apt-get install inotify-tools

on Centos/RHEL (from EPEL repo):

yum --enablerepo epel install inotify-tools

How to use:

inotifywait -re create /tmp/test1/ && echo "Change detected"

Once you create a file echo "change detected" will be triggered which could be just about anything.

The output you get:

Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.
/tmp/test1/test2/test3/ CREATE file
Change detected

PS. -r for recursive -e create to detect new files.

How to determine whether files have been changed in a directory tree without traversing the entire tree?

ZFS provides the capability via zfs diff ... Per the Oracle Solaris 11.2 documentation:

Identifying ZFS Snapshot Differences (zfs diff)

You can determine ZFS snapshot differences by using the zfs diff
command.

For example, assume that the following two snapshots are created:

$ ls /tank/home/tim
fileA
$ zfs snapshot tank/home/tim@snap1
$ ls /tank/home/tim
fileA fileB
$ zfs snapshot tank/home/tim@snap2

For example, to identify the differences between two snapshots, use
syntax similar to the following:

$ zfs diff tank/home/tim@snap1 tank/home/tim@snap2
M /tank/home/tim/
+ /tank/home/tim/fileB

In the output, the M indicates that the directory has been modified.
The + indicates that fileB exists in the later snapshot.

The R in the following output indicates that a file in a snapshot has
been renamed.

$ mv /tank/cindy/fileB /tank/cindy/fileC
$ zfs snapshot tank/cindy@snap2
$ zfs diff tank/cindy@snap1 tank/cindy@snap2
M /tank/cindy/
R /tank/cindy/fileB -> /tank/cindy/fileC

This does only compare between two snapshots, so you do have to have the ability to create ZFS snapshots to use this effectively.

How to monitor a directory for file changes without using inotifywait?

Depending on the sizes of the files and the nature of the changes you could:

  • Create a checksum (md5, CRC, SHA256) of the files and watch for changes
  • check the size of the files and watch for changes

How do I (recursively?) monitor contents of new directories using inotify?

Well the fastest to implement (but not the fastest in reality) would be to:

  1. Create the initial tree of directories by recursively exploring the children; An example in C/Linux can be found here:

    http://www.lemoda.net/c/recursive-directory/

  2. Add a watch for each subdirectory; When something has been modified or changed you can parse all children recursively and see the differences. Something similar was discussed here:
    How to monitor a folder with all subfolders and files inside?

  3. If this solution doesn't appeal to you, you might try to do a polling mechanism such that you must re-check the whole structure using a thread at a certain time interval.

Hope it helps!

How to continuously monitor the directory using dnotify /inotify command

Inotify itself is a kernel module accesible via calls from e.g. a C program.

https://linux.die.net/man/7/inotify

There is an application suite called inotify-tools, which contains:

inotifywait - wait for changes to files using inotify

http://linux.die.net/man/1/inotifywait

and

inotifywatch - gather filesystem access statistics using inotify

http://linux.die.net/man/1/inotifywatch

You can use inotify directly from command line, e.g. like this to continuously monitor for all changes under home directory (may generate lots of output):

inotifywait -r -m $HOME

And here is a script that monitors continuously and reacts to Apache log activity, copied from the man file of inotifywait:

#!/bin/sh
while inotifywait -e modify /var/log/messages; do
if tail -n1 /var/log/messages | grep httpd; then
kdialog --msgbox "Apache needs love!"
fi
done

Need to monitor directory change, and perform action

This is ugly and naive... but...

#!/bin/bash

WASTHERE=0
MONITORING=/tmp/whatever.dat
LASTBACKUP=/tmp/mybackup.dat
LOGFILE=/tmp/mylog.log

# Just create an empty file to start with
touch "$LASTBACKUP"

while [ 1 ];
do
if [[ ! -e "$MONITORING" ]]; then
if [[ $WASTHERE -ne 0 ]]; then
echo "File is gone! Do something with $LASTBACKUP";
WASTHERE=0
fi
else
WASTHERE=1
ls -l "$MONITORING" >> $LOGFILE
cp "$MONITORING" "$LASTBACKUP"
fi

sleep 5
done

The unfortunate part about this is that if anything happens to the file being 'monitored' while the script is sleeping (content is written to it, for example) and the file is then deleted before the script wakes up, the newly written content will not be in the 'backup.'



Related Topics



Leave a reply



Submit