Comprehensive Guide to Monitoring File System Events with inotifywait
inotifywait is a C library and a set of command-line programs providing a simple interface to inotify.
Installation
emerge --ask inotify-tools
Introduction
The Linux inotify
system provides a powerful mechanism to monitor file system events, allowing applications to watch for changes to files and directories. inotifywait
, a command-line utility leveraging this system, offers a straightforward way to utilize these capabilities in scripts and command-line operations. This guide is designed to showcase a variety of use cases for inotifywait
, from basic monitoring to complex file management tasks, making it an invaluable resource for developers, system administrators, and IT professionals seeking to enhance their toolkit.
Options
| EVENTS | | The following events are valid for use with the -e option | access | A watched file or a file within a watched directory was read from. | modify | A watched file or a file within a watched directory was written to. | attrib | The metadata of a watched file or a file within a watched directory was modified. This includes timestamps, file permissions, extended attributes etc. | close_write | A watched file or a file within a watched directory was closed, after being opened in writable mode. This does not necessarily imply the file was written to. | close_nowrite | A watched file or a file within a watched directory was closed, after being opened in read-only mode. | close | A watched file or a file within a watched directory was closed, regardless of how it was opened. Note that this is actually implemented simply by listening for both close_write and close_nowrite, hence all close events received will be output as one of these, not CLOSE. | open | A watched file or a file within a watched directory was opened. | moved_to | A file or directory was moved into a watched directory. This event occurs even if the file is simply moved from and to the same directory. | moved_from | A file or directory was moved from a watched directory. This event occurs even if the file is simply moved from and to the same directory. | move | A file or directory was moved from or to a watched directory. | move_self | A watched file or directory was moved. After this event, the file or directory is no longer being watched. | create | A file or directory was created within a watched directory. | delete | A file or directory within a watched directory was deleted. | delete_self | A watched file or directory was deleted. | unmount | The filesystem on which a watched file or directory resides was unmounted.
Additional Options
Monitor files that is edited/created/deleted/opened/closed in a dir
inotifywait -m -q -r \
--format '%T % e %w%f' \
--timefmt '%d/%m/%Y-%H:%M:%S%z' /mnt/usb/glftpd/ | \
while IFS=' ' read -r time event file; do
echo "file: $file"
done
Notify file change
while inotifywait -q -e modify filename >/dev/null; do
echo "filename is changed"
# do whatever else you need to do
done
Monitor dir every minute
inotifywatch -v -e access -e open -e create -e modify -t 60 -r
Close write
while inotifywait -e close_write myfile.py; do ./myfile.sh; done
Monitor a single directory (non-recursive)
inotifywait -q -m -e create /path/to/directory
Exclude specific files or directories
inotifywait -q -m -r --exclude '(^\.git|node_modules)' /path/to/directory
!!! Example "Only monitor specific file types
inotifywait -q -m -r --include '\.txt$' /path/to/directory"
Display events as they occur
inotifywait -m -r -e create /path/to/directory
Scripts
Run rsync by notify timeĀ¶
cwd=$(pwd)
inotifywait -mr \
--timefmt '%d/%m/%y %H:%M' --format '%T %w %f' \
-e close_write /tmp/test |
while read -r date time dir file; do
changed_abs=${dir}${file}
changed_rel=${changed_abs#"$cwd"/}
rsync --progress --relative -vrae 'ssh -p 22' "$changed_rel" \
usernam@example.com:/backup/root/dir && \
echo "At ${time} on ${date}, file $changed_abs was backed up via rsync" >&2
done
If filename exist and inotiwait notice a change run script
inotifywait -e close_write,moved_to,create -m . |
while read -r directory events filename; do
if [ "$filename" = "myfile.py" ]; then
./myfile.py
fi
done
Monitor file and print last line when file is modified
inotifywait -r -e modify -m . \
| while read -r directory events filename; do
tail -n1 $filename;
done
Print filename that was modified, created, or closed
inotifywait -r -e close_write,moved_to,create,modify -m $LOGDIR |
while read -r directory events filename; do
echo $filename
done
Trigger a command each time a file is created in a directory (inotify)
inotifywait -mrq -e CREATE format %w%f /path/to/dir |
while read FILE; do
chmod g=u "$FILE";
done
Immediately put execute permission on any file saved/created in $HOME/bin
inotifywait -mr -e CREATE $HOME/bin/ |
while read i; do
chmod +x $(echo "$i" | sed 's/ \S* //');
done
Debug how files are being accessed by a process
inotifywait -m -r .
Print last filename that has been modified
inotifywait -m --exclude "[^j].$|[^s]$" /path -e create -e moved_to |
while read dir action file; do
echo "The file '$file' appeared in directory '$dir' via '$action'"
done
httpd-logs
A short shell script to efficiently wait for httpd-related log messages and do something appropriate
while ! inotifywait -e modify /var/log/messages; do
if tail -n1 /var/log/messages | grep httpd; then
kdialog --msgbox "Apache needs love!"
fi
done
Custom format
inotifywait -m -r --format '%:e %f' ~/test
Enforce file permissions
inotifywait -qmr -e 'moved_to,create' --format '%w%f%0' --no-newline ~/test |\
while IFS= read -r -d '' file;do
chmod -v a+rX "$file"
done
Block all brute-force attacks in realtime (IPv4/SSH)
inotifywait -r -q --format %w /var/log/auth.log \
|grep -i "Failed pass" \
|tail -n 1 \
|grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}';
iptables -I INPUT -i eth0 -s "$(cat /var/log/auth.log \
|grep "authentication failure; l" \
|awk -Frhost= '{print $2}' \
|tail -n 1)" -j DROP
Notify when true
event=$(inotifywait --format '%e' /var/log) || exit
[ "$event" = "MODIFY" ] && echo 'file modified!' >&2
[ "$event" = "DELETE_SELF" ] && echo 'file deleted!' >&2
Monitor dir and if file extension match, remove metadata (example)"
inotifywait -m /path -e create -e moved_to |
while read path action file; do
if [[ "$file" =~ .*xml$ ]]; then # Does the file end with .xml?
echo "xml file" # If so, do your thing here!
fi
done
Print filename with full path for all newly created files
inotifywait -q -m -r -e create /home/wuseman/emagnet/websites/nohide.space/ |
while read -r directory event filename; do
if [[ $event == "CREATE" ]]; then
echo "File created: $directory$filename"
fi
done
Print filename for all modified files
inotifywait -q -m -r -e modify /path/to/directory |
while read -r directory event filename; do
if [[ $event == "MODIFY" ]]; then
echo "File modified: $filename"
fi
done
Execute a command on file creation
inotifywait -q -m -r -e create /path/to/directory |
while read -r directory event filename; do
if [[ $event == "CREATE" ]]; then
# Replace the following line with your desired command
command_to_execute "$filename"
fi
done
Print filename and timestamp for all modified files
inotifywait -q -m -r -e modify /path/to/directory |
while read -r directory event filename; do
if [[ $event == "MODIFY" ]]; then
echo "File modified: $filename"
echo "Timestamp: $(date +"%Y-%m-%d %H:%M:%S")"
fi
done
Perform an action on modified files
inotifywait -q -m -r -e modify /path/to/directory |
while read -r directory event filename; do
if [[ $event == "MODIFY" ]]; then
# Replace the following line with your desired action
echo "File modified: $filename"
# Perform your action here
fi
done
Track specific file extensions
inotifywait -q -m -r -e modify --include '\.(txt|csv)$' /path/to/directory |
while read -r directory event filename; do
if [[ $event == "MODIFY" ]]; then
echo "File modified: $filename"
fi
done
Print filename and size for all modified files
inotifywait -q -m -r -e modify --format '%f %s' /path/to/directory |
while read -r filename size; do
echo "File modified: $filename"
echo "Size: $size bytes"
done
Monitor file deletions
inotifywait -q -m -r -e delete /path/to/directory |
while read -r directory event filename; do
if [[ $event == "DELETE" ]]; then
echo "File deleted: $filename"
fi
done
Track directory modifications
inotifywait -q -m -r -e modify --format '%w%f' /path/to/directory |
while read -r modified_path; do
echo "Directory modified: $modified_path"
done
Exclude specific file types
inotifywait -q -m -r -e modify --exclude '\.(jpg|png)$' /path/to/directory |
while read -r directory event filename; do
if [[ $event == "MODIFY" ]]; then
echo "File modified: $filename"
fi
done
Print filename and event type
inotifywait -q -m -r -e modify --format '%w%f %e' /path/to/directory |
while read -r modified_path event_type; do
echo "File modified: $modified_path"
echo "Event type: $event_type"
done
Print detailed information using JSON format
inotifywait -q -m -r -e modify --format '{"path": "%w%f", "event": "%e"}' /path/to/directory |
while read -r json_data; do
echo "Received event:"
echo "$json_data"
# Process the JSON data as needed
done
Custom output format with additional information
inotifywait -q -m -r -e modify --format 'File: %w%f, Event: %e, Timestamp: %T' /path/to/directory |
while read -r output; do
echo "$output"
done
!!! Example "To watch for created files and delete them if they are not of type .xt
, you can use the following script:
```bash
inotifywait -q -m -r -e create --format '%w%f' /path/to/directory |
while read -r created_file; do
if [[ ! $created_file =~ \.xt$ ]]; then
echo "Deleting file: $created_file"
rm "$created_file"
fi
done
```
Watch multiple events
This command monitors the specified directory (/path/to/directory
) for multiple events (create
, modify
, and delete
). The -e
option is used to specify the events to watch, separated by commas.
bash inotifywait -q -m -r -e create,modify,delete /path/to/directory