Monitoring filesystems with inotify
inotify is a Linux kernel subsystem which allows user land applications to watch for filesystem events, such as files being modified. inotify has been part of the Linux kernel since version 2.6.13, and therefore should already be available in modern Linux distributions.
inotify-tools
A quick way to get started with inotify is by installing inotify-tools
. On
CentOS 7 inotify-tools
can be installed from
EPEL:
yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install inotify-tools
Once the package is installed you should be able to use
inotifywatch and inotifywait.
By default inotifywait
will run until a inode event matching the arguments
passed to it occurs. For example:
inotifywait --event delete_self /tmp/foobar
The command above will wait until /tmp/foobar
is deleted, the output of the
command will look similar to the following:
$ inotifywait --event delete_self /tmp/foobar
Setting up watches.
Watches established.
/tmp/foobar DELETE_SELF
$
The inotifywatch
command works in a similar way, except it counts events and
produces a summary. For example the command below will watch /etc/passwd
and
/etc/shadow
for 60 seconds:
inotifywatch -t 60 /etc/passwd /etc/shadow
The output of the command will be similar to the following:
$ inotifywatch -t 60 /etc/passwd /etc/shadow
Establishing watches...
Finished establishing watches, now collecting statistics.
total access attrib close_write close_nowrite open delete_self filename
16 5 1 1 3 4 1 /etc/passwd
7 2 1 1 0 1 1 /etc/shadow
$
Automatically running Make
A fairly common sequence when programming is running through the following steps:
- Modify code
- Re-compile
- Test code
A simple way to automate this is to poll the filesystem for changes, this can be done with a script similar to the following:
while true; do
if find src/ -mmin 1 > /dev/null; do
make
else
sleep 10
fi
done
However this has two main drawbacks, you're constantly having to check files
for changes, and if you're unlucky you might have to wait the entire interval
between polling, 10 seconds in the example above, before make
recompiles the
code.
To get around this inotifywait
can be used to monitor the source files for
changes:
while true; do
# Wait for changes in the src/ directory
inotifywait \
--recursive \
--event create \
--event modify \
--exclude '.swp$' \
src/
# Run make after a new change
make
done
Note: --exclude
is used to prevent inotifiywait
monitoring swap files
written by Vim.
Processing inbound files
Another common use for inotify is watching input directories for new files. For example you could set up a script to automatically create thumbnails for new images:
#!/bin/sh
#
# Generate thumbnails for new JPG files.
#
WATCH_DIR=/var/images
inotifywait \
--monitor \
--recursive \
--event close_write \
--exclude '.*_thumb.jpg$' \
--format='%w%f' "${WATCH_DIR}" | while read new_file
do
mime_type="$(file --brief --mime-type "$new_file")"
if [ "$mime_type" = 'image/jpeg' ]; then
thumb_name="$(echo "$new_file" | sed 's/\.[a-z]*$//')_thumb.jpg"
echo "Creating: ${thumb_name}"
convert "$new_file" -resize 200 -strip "$thumb_name"
else
echo "Skipping ${new_file}, incorrect mime type (${mime_type})"
fi
done
When the script above is run it will start watching /var/images
for new JPG
files. Files can then be copied to the directory, e.g.:
$ scp cat.jpg host.example.com:/var/images
[email protected]'s password:
The script will detect the new file and make the corresponding thumbnail image
(cat_thumb.jpg
):
$ generate_thumbnails.sh
Setting up watches. Beware: since -r was given, this may take a while!
Watches established.
Creating: /var/images/cat_thumb.jpg