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:
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/
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?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
Check If a Variable Exists in a List in Bash
Linux Time Command Microseconds or Better Accuracy
Linux Shell Script to Add Leading Zeros to File Names
Append Date to Filename in Linux
Why Linux/Gnu Linker Chose Address 0X400000
How to Export a Variable in Bash
Compare Integer in Bash, Unary Operator Expected
Why Doesn't Linux Use the Hardware Context Switch via the Tss
Replace the First Line in a Text File by a String
How to Script a "Yes" Response for Installing Programs
Creating Executable Files in Linux
What's the Point of Eval/Bash -C as Opposed to Just Evaluating a Variable
Bash: Infinite Sleep (Infinite Blocking)
Crt1.O: in Function '_Start': - Undefined Reference to 'Main' in Linux
How to Get Amount of Queued Data for Udp Socket