Skip to content

Instantly share code, notes, and snippets.

@TheDelta
Created November 30, 2022 00:24
Show Gist options
  • Select an option

  • Save TheDelta/d54753845b8fe29f57656d5d4be9c9d7 to your computer and use it in GitHub Desktop.

Select an option

Save TheDelta/d54753845b8fe29f57656d5d4be9c9d7 to your computer and use it in GitHub Desktop.

Revisions

  1. TheDelta created this gist Nov 30, 2022.
    178 changes: 178 additions & 0 deletions dir-watcher.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,178 @@
    #!/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