Skip to content

Instantly share code, notes, and snippets.

@TheDelta
Created November 30, 2022 00:24
Show Gist options
  • Save TheDelta/d54753845b8fe29f57656d5d4be9c9d7 to your computer and use it in GitHub Desktop.
Save TheDelta/d54753845b8fe29f57656d5d4be9c9d7 to your computer and use it in GitHub Desktop.
Directory Watcher for linux about file changes
#!/bin/bash
# @Author: Alexander 'Delta' Diller
# @Date: 2022-11-29 23:32:48
# @Description Monitor a folder recursiveley and sents an email notification
# inotifywait 3.14
# Wait for a particular event on a file or set of files.
# Usage: inotifywait [ options ] file1 [ file2 ] [ file3 ] [ ... ]
# Options:
# -h|--help Show this help text.
# @<file> Exclude the specified file from being watched.
# --exclude <pattern>
# Exclude all events on files matching the
# extended regular expression <pattern>.
# --excludei <pattern>
# Like --exclude but case insensitive.
# -m|--monitor Keep listening for events forever. Without
# this option, inotifywait will exit after one
# event is received.
# -d|--daemon Same as --monitor, except run in the background
# logging events to a file specified by --outfile.
# Implies --syslog.
# -r|--recursive Watch directories recursively.
# --fromfile <file>
# Read files to watch from <file> or `-' for stdin.
# -o|--outfile <file>
# Print events to <file> rather than stdout.
# -s|--syslog Send errors to syslog rather than stderr.
# -q|--quiet Print less (only print events).
# -qq Print nothing (not even events).
# --format <fmt> Print using a specified printf-like format
# string; read the man page for more details.
# --timefmt <fmt> strftime-compatible format string for use with
# %T in --format string.
# -c|--csv Print events in CSV format.
# -t|--timeout <seconds>
# When listening for a single event, time out after
# waiting for an event for <seconds> seconds.
# If <seconds> is 0, inotifywait will never time out.
# -e|--event <event1> [ -e|--event <event2> ... ]
# Listen for specific event(s). If omitted, all events are
# listened for.
# Exit status:
# 0 - An event you asked to watch for was received.
# 1 - An event you did not ask to watch for was received
# (usually delete_self or unmount), or some error occurred.
# 2 - The --timeout option was given and no events occurred
# in the specified interval of time.
# Events:
# access file or directory contents were read
# modify file or directory contents were written
# attrib file or directory attributes changed
# close_write file or directory closed, after being opened in
# writable mode
# close_nowrite file or directory closed, after being opened in
# read-only mode
# close file or directory closed, regardless of read/write mode
# open file or directory opened
# moved_to file or directory moved to watched directory
# moved_from file or directory moved from watched directory
# move file or directory moved to or from watched directory
# create file or directory created within watched directory
# delete file or directory deleted within watched directory
# delete_self file or directory was deleted
# unmount file system containing file or directory unmounted
ACTION=${1:-HELP}
FOLDER=${2:-"/root"} # Folder to watch
EMAIL=${3:-"Delta@ugx-mods.com"} # Email to send notification to
ID=$(echo -n "$FOLDER" | md5sum | cut -d ' ' -f 1)
AUDIT_FILE=/root/watcher-audit-${ID}.log
# --- color helpers ---
red=$(tput setaf 1)
green=$(tput setaf 2)
yellow=$(tput setaf 3)
cyan=$(tput setaf 6)
reset=$(tput sgr0)
# --- LOGIC ---
type -P inotifywait &>/dev/null || {
echo "${red}Install ionotify${reset} | ${yellow}apt-get install inotify-tools"
exit 1
}
if [ -z "$FOLDER" ]; then
echo "${red}Folder param is missing!"
exit 1
fi
function is_already_running {
if [ "$(pgrep -a inotifywait | grep -c "$FOLDER")" -gt 0 ]; then
return
fi
false
}
function start {
if is_already_running; then
echo "${red}A process monitoring ${yellow}$FOLDER${red} is already running:"
echo "${cyan}$(pgrep -a inotifywait | grep "$FOLDER")"
exit 1
fi
if [ -z "$EMAIL" ]; then
echo "${red}EMAIL is missing!"
exit 1
fi
if [ -d "$FOLDER" ]; then
echo "${green}Monitoring folder (recursively) ${yellow}$FOLDER${green} for changes - sending alerts to ${cyan}$EMAIL"
while inotifywait -r -e create -e modify -e attrib -e move -e delete "$FOLDER" -o "$AUDIT_FILE"; do
sleep 1
changes="$(cat "${AUDIT_FILE}")"
echo "The following changes occured at $FOLDER : $changes" | mail -s "[WATCHER] Change in $FOLDER" "$EMAIL"
rm "$AUDIT_FILE"
touch "$AUDIT_FILE"
done
else
echo "Error: Folder $FOLDER not found!"
fi
}
function status {
if is_already_running; then
echo "${green}Monitoring is running${reset} for ${yellow}$FOLDER${reset} [${cyan}$ID${reset}]"
else
echo "${red}Monitoring is NOT running${reset} for ${yellow}$FOLDER${reset} [${cyan}$ID${reset}]"
fi
}
function stop {
# if a inotifywait for this file is already running
if ! is_already_running; then
echo "${red}A process monitoring ${yellow}$FOLDER${red} is not running"
if [ -z "$AUDIT_FILE" ]; then
echo "${yellow}Audit file ${cyan}$AUDIT_FILE${yellow} does exist though, you might want to delete it manually (kept in case you need it)"
exit 1
fi
exit 1
fi
kill -9 "$(pgrep -f "inotifywait.*${FOLDER}")"
rm "$AUDIT_FILE"
echo "${green}Process stopped and audit file removed"
}
case "$ACTION" in
"start")
start
exit 0
;;
"status")
status
exit 0
;;
"stop")
stop
exit 0
;;
*)
echo "Usage dir-watcher.sh <action=start|stop|status> <dir> <email>"
exit 1
;;
esac
@TheDelta
Copy link
Author

⚠️ Script has some default parm values set, like email and folder! Either remove or change (you don't want to send me your changes 🤣)

usage: dir-watcher.sh <action> <path> <email>

start: dir-watcher.sh start /some/folder email@example.de (or omit params after action to use default values)
status: dir-watcher.sh status /some/folder
stop: dir-watcher.sh stop /some/folder

To keep it in background, use screen

start sceen: screen -S MyTask -dm bash -c "dir-watcher.sh /some/folder email@example.de"
stop screen: screen -S MyTask -X quit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment