Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- SCRIPT_VER="Folder Owner Enforcer v0.5.3a"
- # Written by
- # reddit: https://www.reddit.com/user/GeorgeT93
- # pastebin: https://pastebin.com/u/GeorgeT93
- # script pastebin: https://pastebin.com/qRSWAKp1
- # ==========================================================================================================
- # NOTES - START
- # REQUIREMENTS:
- # - inotify-tools (For Raspbian: sudo apt-get install inotify-tools)
- # - The user used to create and invoke the script must have sudo privileges.
- # LATEST UPDATE INFO
- # v0.5.3a Update (2019-04-05) - Added code to identify logged in users when deletions are
- # detected. This is just to let admins know who was logged in at the time a file or folder
- # was deleted. This functionality can be disabled by changing the SHOW_USERS_ON_DELETE
- # value to disabled (0) in the advanced options in the user-defined variables section.
- # If your distribution does not have the following commands available, or if their output
- # deviates dramatically from Debian-based distributions, then disable SHOW_USERS_ON_DELETE.
- # The commands used to identify users are ps, grep, tr and awk.
- # v0.5.2a Update (2019-04-04) - Added logic to determine if a new item in the root folder
- # is a file or a folder. This prevents the script from restarting when it's just a file
- # that was detected, as nothing is enforced on items in the root folder. Also added a 5
- # second delay to the function that terminates other running instances of the script in
- # order to give the system time to properly close the existing inotifywait instance
- # (rather than killing it prematurely.)
- # v0.5.1a Update (2019-04-03) - Fixed issue with logfile not creating a new file on events
- # that occurred on different dates. Also fixed the extra whitespace issue when a newly
- # detected file or folder name did not contain any spaces in the path. Finally, the script
- # now records file deletions that occur in monitored folders.
- # GENERAL INFORMATION
- # This script scans the directories located in ROOTPATH, and retrieves owner and group info
- # for each. It then monitors the ROOTPATH (recursively) for any added files or directories,
- # and when new ones are detected, the script changes the ownership and group of the file
- # or directory to the owner and group of the directory that it was placed in, and then sets
- # any defined permissions.
- # I wrote it because I have a small SFTP server with only a couple of users, but I kept
- # having issues when putting files into a user's directory, as they were unable to be
- # downloaded because the ownership and group of the file were set to my admin user.
- # As such, I had to remind myself to change the ownership of anything I put into a user's
- # folder every time or I would get the inevitable phone call or text telling me the file(s)
- # couldn't be downloaded.
- # With this script, when anything is put in someone's folder, the item is given the ownership and
- # group of the folder it was placed/created in, and the defined permissions mask is applied,
- # regardless of how deep in a user's folder the item was placed. I wrote it to solve an issue when,
- # for example, user1 uploaded files into a new folder in user2's or user3's folder. The new FOLDER
- # had the correct owner, group and permissions, but the files IN the new folder did NOT have the
- # right permissions (everything was read-only by other group members.) However, if user1 put the
- # files directly into a user's base folder (not in a new sub-folder), all the permissions were
- # applied correctly. Since I typically drop files directly into a user's folder from a mapped drive
- # on my local network, anything I put into any user's folder would have the ownership and group set
- # to my "admin" user, even though my admin user account is a member of the sftp group that all other
- # users are members of. Since I couldn't find another way to do it, I decided to write this script
- # to do it for me.
- # COMMAND LINE OPTIONS
- # Command line options - If you invoke the script with no arguments, then the values set in this
- # script will be used for all functions. You can over-ride some of the settings in the script using
- # command line arguments. The full list of arguments can be seen by typing:
- # folder-owner-enforcer --help
- # NOTES - END
- # ==========================================================================================================
- # INSTALLATION - START
- # As the script was written on and for a Raspberry Pi, the following instuctions assume
- # Raspbian Stretch as the distribution. The script should work on other distributions
- # that inotify-tools runs on, but note that some commands and/or paths may be different.
- # 1.) If inotify-tools is not installed, use the following command (on Raspbian)
- # $ sudo apt-get install inotify-tools
- # 2.) Change to the /usr/local/bin folder
- # $ cd /usr/local/bin
- # 3.) Create the file and open it in edit mode
- # $ sudo nano folder-owner-enforcer
- # 4.) Paste the script into the open file
- # 5.) Edit the USER-DEFINED VARIABLES section, setting the values you wish to use. Be aware the the
- # LOGFILEPATH= value is set to /tmp by default. The /tmp directory is cleared on each system restart,
- # so if you wish to maintain copies of the log files, you should point the LOGFILEPATH= value to the
- # directory you wish to store your logs. If you decide to keep logs long-term, you should think of
- # either offloading them to another system for archival purposes (if needed), or creating a cron job
- # to run at a regular interval to clean up old, unwanted logs. For my setup, I don't need to retain
- # any old logs, as I am usually only concerned with the last job run, so using the /tmp folder for
- # logging works for my particular requirements.
- # 6.) Save (<ctrl>+o) and exit (<ctrl>+x) the nano editor
- # 7.) Set the script to executable
- # $ sudo chmod +x folder-owner-enforcer
- # 8.) Set up auto run using one of the following methods (DO NOT USE BOTH)
- # Method 1 - (Using cron) This is the preferred method as it essentially runs invisibly to the user.
- # 8_1a.) Launch the crontab editor
- # $ crontab -e
- # 8_1b.) Add the following line to the bottom of the file, substituting the user you wish to run the
- # script as. You MUST define a user that has sudo permission and you should NOT use the root
- # user. The user defined in the command below is 'pi', so you would switch 'pi' to your user's
- # name.
- # @reboot -u pi /usr/local/bin/folder-owner-enforcer
- # 8_1c.) Save (<ctrl+o>) and exit (<ctrl+x>) the crontab editor.
- # Method 2 - (Using LXDE GUI autostart) This should only be used with systems that boot directly into the
- # GUI, otherwise the script won't automatically launch until the GUI is started manually, but
- # it is useful if you boot into the GUI AND want a terminal window open logging the script
- # actions. Note, however, that if you choose this method and you close the terminal window, the
- # script will also exit and will need to be restarted manually to re-enable enforcement.
- # 8_2a.) The autorun location may be found in a different path on different distributions. This script
- # was developed on Raspbian Stretch, so the paths reflected here are based on that platform. So
- # on a Raspberry Pi running Raspbian Stretch, the path to edit autostart file is used in this
- # example command, and your path may be different. Using a terminal window (if the GUI is loaded)
- # or at a regular CLI terminal, use the following command (substituting your path if neccesary)
- # $ sudo nano /etc/xdg/lxsession/LXDE-pi/autostart
- # 8_2b.) Add the following line to the BOTTOM of the autostart file (including quotes.)
- # lxterminal --command="/usr/local/bin/folder-owner-enforcer"
- # 8_2c.) Save (<ctrl>+o) and exit (<ctrl>+x) from the nano editor.
- # 9.) Restart the system. When the system restarts, you can check if the script is running a couple of ways,
- # depending on how you are auto starting it.
- # - If you boot straight into the GUI and you configured the LXDE autostart file method, you should see a
- # terminal window open showing the output from the script.
- # - If you boot straight into the GUI and you configured the crontab @reboot autostart method, you can click
- # on the task manager and look for the inotifywait instance that should be running.
- # - If you boot into the CLI or are connecting remotely through SSH, and are using the crontab @reboot method,
- # you can issue the command "pidof inotifywait" (without the quotes.) If it returns a number, the script is
- # running. You can also use the -viewlog command line option (folder-owner-enforcer -viewlog) to view the
- # current day's log. It should show that the script started up successfully. Note that this method is only
- # really valid on the same day as a system restart, as the log could remain empty for days if nothing has
- # been added or deleted from watched paths.
- # That's it. You really shouldn't have to touch it again once it's been configured correctly and set to automatically
- # start on system restarts. While it is running, any items put into a user's folder will have their ownership set to
- # the folder's owner and whatever permission mask you've defined for the script will be applied.
- # INSTALLATION - END
- # ==========================================================================================================
- # USER-DEFINED VARIABLES - START - Adjust these values to configure the script for your setup.
- # PATHS
- # Set the base folder. All your USER BASE FOLDERS should be located IN this path.
- ROOTPATH="/mnt/studio/shares/sftp"
- # PERMISSIONS OPTIONS
- # Set the ENABLEMASK value to 1 to apply the USEMASK value to new items. Set to 0 to disable
- # applying the mask. Note that when disabled, only OWNER and GROUP are changed for detected items,
- # so whatever permissions that already exist on the item will remain intact. Note that you can also
- # disable the mask when launching the script by using the "-nomask" command line option. Using the
- # command line option will always take priority over the value set here.
- ENABLEMASK=1
- # Set the default permissions mask you want applied to the new item (file or folder).
- # The default value is 770 (full access for owner and group members, everyone else is denied.)
- # Note that if using the -setmask= option from the command line, the script will use the value that
- # you define at the command line for the mask and not the value set below. Also be aware that if
- # ENABLEMASK is 0 or if the script is called with the -nomask argument, this value isn't enforced.
- USEMASK=770
- # Set PRESERVE to 1 if you wish to preserve existing owners, groups and permissions on existing
- # files and folders in watched folders and only enforce owner, group and permissions on new items.
- # Setting this to 0 (which is the default) will NOT preserve existing owners, groups or permissions
- # and will enforce the ownership, group and permissions (if mask is enabled) on all items, new and
- # existing. Note that defining -preserve at the command line is the same as setting this value to 1.
- PRESERVE=0
- # Set TESTRUN to 1 if you want to test your settings without applying them to the actual folders.
- # Using testrun while configuring the script is a good idea so you can see the folders identified
- # by the script, along with the detected owners and groups. This allows you to view the owners
- # and groups that will be enforced on each respective folder without making any changes before
- # applying enforcement. Note that -testrun can be defined as a command line argument and will
- # override anything defined here, and defining either the -nomask and -setmask options at the
- # command line will also override this setting.
- TESTRUN=0
- # Set the RESTARTDELAY to the value (in seconds) that you want the script to wait before restarting
- # enforcement when a new item is detected in the root folder. This is intended to give the administrator
- # time to configure the owner and group when adding a new user folder before the script restarts the
- # scan and enforcement process. This setting can be overridden by using the command line option
- # -delay=##
- # where ## is the time in seconds.
- RESTARTDELAY=60
- # Set the NOKILL value to enable or disable terminating the inotifywait process. If you are running other
- # instances of inotifywait (outside of this script), the set the NOKILL value to 1 to prevent this script
- # from issuing the "killall inotifywait" command that this script uses to terminate any existing inotifywait
- # processes when initializing and during the process of restarting enforcement to ensure that any abandoned
- # instances are no longer running. If you use inotifywait for monitoring other locations, then this value
- # must be set to 1 to ensure that your other instances remain running. Note that you can also enable nokill
- # by using the -nokill command line option which is the same as setting this value to 1. For all other cases,
- # this should be set to 0.
- NOKILL=0
- # ENABLELOG turns logging on (1) or off (0). LOGFILEPATH Defines the path to store the logfile, DO NOT
- # include a trailing "/". Make sure this path is writeable by the user that runs the script. Change this from
- # /tmp to another folder to prevent logs from being cleared on system restarts.
- ENABLELOG=1
- LOGFILEPATH="/tmp"
- # ADVANCED SETTINGS - These values should not typically need to be touched. They are provided here for advanced
- # configurations such as defining a different system /tmp directory or allowing multiple instances of the script.
- # SYS_TMP_PATH=<path> Temp files path (required). This should remain pointed at /tmp on most systems. If you
- # are using a different directory for temporary files on your system, change the path to match your
- # system's /tmp path. Otherwise, leave this value alone. Default value is "/tmp" (including the quotes.)
- SYS_TMP_PATH="/tmp"
- # ALLOW_MULTIPLE is DISABLED (0) by default. It prevents multiple instances of inotifywait from running by
- # killing any running instances before starting a new instance. If it is ENABLED (1), it will still issue
- # kill commands to PIDs known to the running instance of the script, but will prevent the KILLALL from
- # being issued so other running instances of inotifywait are left alone.
- ALLOW_MULTIPLE=0
- # SHOW_USERS_ON_DELETE is ENABLED (1) by default. It simply adds the currently logged in users to the output
- # log when file deletions are detected in order to identify who was logged in when files were deleted.
- # Note that if you have issues with users being displayed when files are deleted on other non-Debian-based
- # distributions, then you should set this to DISABLED (0).
- SHOW_USERS_ON_DELETE=1
- # USER-DEFINED VARIABLES - END - DO NOT MODIFY ANYTHING BELOW THIS LINE IF YOU DON'T KNOW WHAT YOU'RE DOING.
- # ==========================================================================================================
- # FUNCTIONS - START
- # ==========================================================================================================
- # TIMESTAMP FUNCTION - START
- TIMESTAMP()
- {
- log_timestamp_date=`date +\%Y-\%m-\%d`
- log_timestamp_hour=`date +\%H`
- log_timestamp_ampm="am"
- # Default value when no argument is passed is the same as "nonew". No newline
- # will be sent with the timestamp, so the next echo statement will appear on
- # the same line as the timestamp.
- sendNewLine=0
- # Check for passed argument. Passed value can be "newline" or "nonew" (default)
- if [ ! -z $1 ]; then
- # Argument passed, so test it.
- case $1 in
- "newline")
- sendNewLine=1
- ;;
- "nonew")
- sendNewLine=0
- ;;
- esac
- fi
- if [ $log_timestamp_hour -gt 11 ]; then
- log_timestamp_hour=$(($log_timestamp_hour-12))
- log_timestamp_ampm="pm"
- fi
- if [ $log_timestamp_hour -eq 0 ]; then
- log_timestamp_hour=12
- fi
- if [ $sendNewLine -eq 1 ]; then
- # Send with a newline character. The next echo will appear on a new line.
- log_timestamp="${log_timestamp_date} ${log_timestamp_hour}:`date +\%M:\%S` ${log_timestamp_ampm}"
- echo -e "\e[96m\e[1m${log_timestamp}\e[0m" 2>&1 | tee -a $TMPLOG
- else
- # Don't send a newline character. Keep next echo on the same line as the timestamp.
- log_timestamp="${log_timestamp_date} ${log_timestamp_hour}:`date +\%M:\%S` ${log_timestamp_ampm}: "
- echo -n -e "\e[96m\e[1m${log_timestamp}\e[0m" 2>&1 | tee -a $TMPLOG
- fi
- }
- # TIMESTAMP FUNCTION - END
- # ==========================================================================================================
- # VALIDATEMASK FUNCTION - START
- VALIDATEMASK()
- {
- maskVal="$USEMASK"
- checkFirstChar=${maskVal::1}
- checkSecondChar=${maskVal:1:1}
- case "$checkFirstChar" in
- "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7")
- # Since the first character was a valid number, make sure the second character is too
- case $checkSecondChar in
- "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7")
- VALIDMASK=1
- ;;
- *)
- # The second character was NOT a valid number. Trigger error.
- echo -e "\e[91m\e[1mERROR!\e[0m Invalid mask was specified. Number [0-7] was expected." 2>&1 | tee -a $TMPLOG
- echo "$SCRIPT_VER has terminated." 2>&1 | tee -a $TMPLOG
- LOG_CLEAN_OUTPUT
- exit 1;
- ;;
- esac
- ;;
- "-"|"+")
- # Since the first character was a valid symbol, make sure the second character is also valid
- case $checkSecondChar in
- "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"r"|"w"|"x")
- VALIDMASK=1
- ;;
- *)
- # The second character was NOT valid. Trigger error.
- echo -e "\e[91m\e[1mERROR!\e[0m Invalid mask was specified. When using + or - for the mask, the" 2>&1 | tee -a $TMPLOG
- echo "next expected character should have been a number [0-7] or a letter [r] [w] or [x]." 2>&1 | tee -a $TMPLOG
- echo "$SCRIPT_VER has terminated." 2>&1 | tee -a $TMPLOG
- LOG_CLEAN_OUTPUT
- exit 1;
- ;;
- esac
- ;;
- "a"|"o"|"g"|"u")
- if [[ $checkSecondChar == "=" ]]; then
- VALIDMASK=1
- else
- echo -e "\e[91m\e[1mERROR!\e[0m Invalid mask was specified. Equal sign expected." 2>&1 | tee -a $TMPLOG
- echo "$SCRIPT_VER has terminated." 2>&1 | tee -a $TMPLOG
- LOG_CLEAN_OUTPUT
- exit 1;
- fi
- ;;
- *)
- # The first character of the second argument was NOT a valid mask character. Trigger error.
- echo -e "\e[91m\e[1mERROR!\e[0m Invalid mask was specified." 2>&1 | tee -a $TMPLOG
- echo "$SCRIPT_VER has terminated." 2>&1 | tee -a $TMPLOG
- LOG_CLEAN_OUTPUT
- exit 1;
- ;;
- esac
- LOG_CLEAN_OUTPUT
- }
- # VALIDATEMASK FUNCTION - END
- # ==========================================================================================================
- # SCANFOLDERS FUNCTION - START
- SCANFOLDERS()
- {
- # SCANFOLDERS DETERMINES ENFORCEMENT VALUES - START - Cycle through the user folders in the ROOTPATH
- # to identify the paths that will be watched by inotify, and retrieve owner and group
- # information for each user folder to apply to any new (and existing) items in each user's folder.
- # INITIALIZE ARRAYS
- DIRPATH=()
- DIROWNER=()
- DIRGROUP=()
- # IDENTIFY USER FOLDERS - Identify folders IN the defined ROOTPATH variable, getting their name, owner and group, and assign each an id.
- echo -e "\e[96m\e[1m=======================================================================\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[96m\e[1m$SCRIPT_VER - Folder Ownership Scan\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[96m\e[1m=======================================================================\e[0m" 2>&1 | tee -a $TMPLOG
- DIRID=1
- for FOLDER in $ROOTPATH
- do
- if [[ -d "$FOLDER" && ! -L "$FOLDER" ]]; then
- tmpPath="${FOLDER}"
- TIMESTAMP newline
- echo -e "\e[34m\e[1mIdentified Folder for Enforcement:\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e " \e[34m\e[1m$tmpPath\e[0m" 2>&1 | tee -a $TMPLOG
- tmpUser=`stat -c "%U" "$tmpPath"`
- tmpGroup=`stat -c "%G" "$tmpPath"`
- DIRPATH[$DIRID]=$tmpPath
- DIROWNER[$DIRID]=$tmpUser
- DIRGROUP[$DIRID]=$tmpGroup
- echo -e "\e[1mRetrieving and storing owner information\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e " Folder Record ID: \e[1m $DIRID\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e " Enforcement Path: \e[34m\e[1m${DIRPATH[$DIRID]}\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e " Identified Owner: \e[35m\e[1m${DIROWNER[$DIRID]}\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e " Identified Group: \e[104m\e[1m${DIRGROUP[$DIRID]}\e[0m" 2>&1 | tee -a $TMPLOG
- # ASSIGN THE FOLDER OWNER AND GROUP TO ALL ITEMS IN THE CURRENT FOLDER RECURSIVELY
- # This is to ensure that existing files and folders in each user's directory have the correct owner
- # group and permissions enforced.
- if [ $TESTRUN -eq 1 ]; then
- # This is a Test Run so do not enforce anything
- echo -e "\e[42m\e[1mTest Run\e[0m" 2>&1 | tee -a $TMPLOG
- echo "ownership and group information is not being enforced. If enforcement" 2>&1 | tee -a $TMPLOG
- echo "were enabled, all existing items and any new items added to" 2>&1 | tee -a $TMPLOG
- echo -e "\e[34m\e[1m${DIRPATH[$DIRID]}\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "would have \e[35m\e[1m${DIROWNER[$DIRID]}\e[0m:\e[104m\e[1m${DIRGROUP[$DIRID]}\e[0m" 2>&1 | tee -a $TMPLOG
- echo "enforced as owner and group if this were not a test run." 2>&1 | tee -a $TMPLOG
- else
- # This is NOT a Test Run - Enforce based on settings
- if [ $PRESERVE -eq 1 ]; then
- # Not a test run but preserve is on, so enforce ownership and group only on new files
- echo -e "Enforcing owner and group only on new items in:" 2>&1 | tee -a $TMPLOG
- echo -e " \e[34m\e[1m${DIRPATH[$DIRID]}\e[0m" 2>&1 | tee -a $TMPLOG
- else
- # Not a test run and preserve is off so enforce ownership and group on existing files
- echo "Enforcing owner and group on existing items in:" 2>&1 | tee -a $TMPLOG
- echo -e " \e[34m\e[1m${DIRPATH[$DIRID]}\e[0m" 2>&1 | tee -a $TMPLOG
- fi
- updMask=0
- if [ $PRESERVE -eq 0 ]; then
- # PRESERVE is off, so enforce owner and group on existing items in detected folder.
- sudo chown -R "${DIROWNER[$DIRID]}":"${DIRGROUP[$DIRID]}" "${DIRPATH[$DIRID]}"
- if [ $? -ne 0 ]; then
- # ERROR SETTING OWNER - GROUP
- echo -e "\e[91m\e[1mERROR!\e[0m Unable to set ownership and group to one or more items in:" 2>&1 | tee -a $TMPLOG
- echo " ${DIRPATH[$DIRID]}" 2>&1 | tee -a $TMPLOG
- else
- # OWNER AND GROUP WERE SET SUCCESSFULLY
- echo -e " \e[32m\e[1mSuccess!\e[0m Owner and group have been changed to:" 2>&1 | tee -a $TMPLOG
- echo -e " \e[35m\e[1m${DIROWNER[$DIRID]}\e[0m:\e[104m\e[1m${DIRGROUP[$DIRID]}\e[0m" 2>&1 | tee -a $TMPLOG
- # Since owner and group were changed successfully, update permissions mask
- updMask=1
- fi
- # If the owner and group were successfully changed AND $ENABLEMASK is 'on' (1)
- if [[ $updMask -eq 1 && $ENABLEMASK -eq 1 ]]; then
- echo -e "Enforcing \e[7m$USEMASK\e[0m permissions on all items in:" 2>&1 | tee -a $TMPLOG
- echo -e " \e[34m\e[1m${DIRPATH[$DIRID]}\e[0m" 2>&1 | tee -a $TMPLOG
- sudo chmod "$USEMASK" -R "${DIRPATH[$DIRID]}"
- if [ $? -ne 0 ]; then
- # ERROR SETTING PERMISSIONS MASK
- echo -e "\e[91m\e[1mERROR!\e[0m Unable to set permissions on one or more items in" 2>&1 | tee -a $TMPLOG
- echo " ${DIRPATH[$DIRID]}" 2>&1 | tee -a $TMPLOG
- echo "" 2>&1 | tee -a $TMPLOG
- echo -e "\e[34m-------------------------------------------------------------\e[0m" 2>&1 | tee -a $TMPLOG
- else
- # PERMISSIONS SET SUCCESSFULLY
- echo -e " \e[32m\e[1mSuccess!\e[0m Enforced \e[7m$USEMASK\e[0m on ALL items in" 2>&1 | tee -a $TMPLOG
- echo -e " \e[34m\e[1m${DIRPATH[$DIRID]}\e[0m" 2>&1 | tee -a $TMPLOG
- echo "" 2>&1 | tee -a $TMPLOG
- echo -e "\e[34m-------------------------------------------------------------\e[0m" 2>&1 | tee -a $TMPLOG
- # RESET updMask to 0 for next job
- updMask=0
- fi
- else
- # old elif [[ $updMask -eq 1 && $ENABLEMASK -eq 0 ]]; then
- echo "Permission masks are disabled. Permissions will not be changed." 2>&1 | tee -a $TMPLOG
- fi
- else
- # Preserve flag enabled - do not enforce rules on existing items.
- echo -e "\e[42m\e[1mPreserve Mode\e[0m Preserve is enabled. Enforcement will only apply" 2>&1 | tee -a $TMPLOG
- echo "to new items. Owner, group and permissions on existing items will" 2>&1 | tee -a $TMPLOG
- echo "be preserved." 2>&1 | tee -a $TMPLOG
- fi
- # End preserve
- fi
- # End testrun if
- # Increment DIRID for the next record.
- DIRID=$((DIRID+1))
- fi
- done
- LOG_CLEAN_OUTPUT
- }
- # SCANFOLDERS FUNCTION - END
- # ==========================================================================================================
- # ENFORCEMENT FUNCTION - START
- ENFORCEMENT()
- {
- # Begin monitoring BASEPATH (add a trailing slash) folder recursively. React to close_write or moved_to events.
- echo -e "\e[96m\e[1m=======================================================================\e[0m" 2>&1 | tee -a $TMPLOG
- TIMESTAMP newline
- echo -e "\e[96m\e[1m$SCRIPT_VER - Enforcement Started\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[96m\e[1m=======================================================================\e[0m" 2>&1 | tee -a $TMPLOG
- LOG_CLEAN_OUTPUT
- inotifywait -e create,delete -r -m --format "%e %w%f" "${BASEPATH}"/ |
- while read trgEvent updItem;
- do
- echo -e "\e[34m-------------------------------------------------------------\e[0m" 2>&1 | tee -a $TMPLOG
- TIMESTAMP newline
- case $trgEvent in
- # DELETE DETECTED - START
- DELETE|DELETE*)
- echo -e "\e[31m\e[1mDeletion detected:\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e " \e[34m\e[1m$updItem\e[0m" 2>&1 | tee -a $TMPLOG
- if [ $SHOW_USERS_ON_DELETE -eq 1 ]; then
- # SHOW_USERS_ON_DELETE is enabled, so print currently connected users.
- curUsers=$( ps -ef | grep 'shd' | grep -v ^root | grep -v notty | awk '{ print $1 }' | tr '\n' ';' )
- echo -e -n "\e[96m\e[1mCurrent Users: " 2>&1 | tee -a $TMPLOG
- echo -e "\e[21m${curUsers}\e[0m" 2>&1 | tee -a $TMPLOG
- fi
- ;;
- # DELETE DETECTED - END
- # CREATE DETECTED - START
- CREATE|CREATE*)
- echo -e "\e[96m\e[1mNew item detected:\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e " \e[34m\e[1m $updItem\e[0m" 2>&1 | tee -a $TMPLOG
- # Cycle through known monitored folders to determine which known path matches
- # the base path that the updItem was created or moved to.
- DIRCT=${#DIRPATH[@]}
- DIRID=1
- isBasePath=0
- ownerFound=0
- echo -e "Owner and Group Enforcement:" 2>&1 | tee -a $TMPLOG
- while [[ $DIRID -le $DIRCT && $ownerFound -lt 1 ]]
- do
- # updItemPath is the full path with everything to the right of the last slash stripped out
- # so it can be compared to the known BASEPATH to so we can make sure the new item was not
- # created in the root folder.
- updItemPath=${updItem%/*}
- if [[ "$updItemPath" == "$BASEPATH" ]]; then
- # The new item was created in the base (root) path. We will not change anything that is
- # created directly in the root of the user tree.
- echo "Item was created in the root path. $SCRIPT_VER does" 2>&1 | tee -a $TMPLOG
- echo "not enforce items created in or added to the root path." 2>&1 | tee -a $TMPLOG
- # Check if new item is a file or a folder. If it is a folder, enforcement will need to
- # be restarted in order to know the owner and group to be assigned to any items that
- # are created in the new folder. If it is a file, don't do anything as the message
- # above covers the fact that the item will not have ownership or group enforced.
- if [[ -f "${updItem}" ]]; then
- echo -e "\e[34m\e[1m${updItem}\e[0m is a \e[1mfile\e[0m." 2>&1 | tee -a $TMPLOG
- echo -e "Enforcement does \e[1mnot\e[0m need to be restarted." 2>&1 | tee -a $TMPLOG
- isBasePath=1
- ownerFound=1
- else
- if [[ -d "${updItem}" ]]; then
- echo -e "\e[34m\e[1m${updItem}\e[0m is a \e[1mfolder\e[0m." 2>&1 | tee -a $TMPLOG
- echo -e "\e[96m$SCRIPT_VER\e[0m needs to be restarted to establish" 2>&1 | tee -a $TMPLOG
- echo "enforcement on:" 2>&1 | tee -a $TMPLOG
- echo -e " \e[34m\e[1m$updItem\e[0m" 2>&1 | tee -a $TMPLOG
- isBasePath=1
- ownerFound=1
- LOG_CLEAN_OUTPUT
- RESTART_ENFORCE
- fi
- fi
- fi
- if [[ "${updItem}" == *"${DIRPATH[$DIRID]}"* && $isBasePath -eq 0 ]]; then
- curID=$DIRID
- # ASSIGN OWNER GROUP - START
- # Assign the owner and group of the updItem to the owner and group of the folder
- # it was created in or moved to.
- # The wasUpdated flag values: 0=Not Updated, 1=Update Failed (Max retries), 2=Success
- wasUpdated=0
- curRetry=0
- maxRetries=5
- while [ $wasUpdated -lt 1 ]
- do
- sudo chown "${DIROWNER[$curID]}":"${DIRGROUP[$curID]}" "${updItem}"
- if [ $? -ne 0 ]; then
- case $curRetry in
- 0|1)
- echo -n -e "\e[97m\e[1mERROR!\e[0m " 2>&1 | tee -a $TMPLOG
- ;;
- 2|3)
- echo -n -e "\e[93m\e[1mERROR!\e[0m " 2>&1 | tee -a $TMPLOG
- ;;
- 4|5)
- echo -n -e "\e[91m\e[1mERROR!\e[0m " 2>&1 | tee -a $TMPLOG
- ;;
- esac
- echo "Unable to change ownership of ${updItem}." 2>&1 | tee -a $TMPLOG
- curRetry=$((curRetry+1))
- case $curRetry in
- 1)
- # Workaround for issue where new folders that have no spaces in their name have
- # whitespace added to the end of the variable when it is read by the script making,
- # it impossible to set the ownership and permissions. This workaround will try
- # removing the last character, which should be whitespace, then try again.
- echo "Attempting workaround for known whitespace issue and retrying." 2>&1 | tee -a $TMPLOG
- tmpItem="$updItem"
- updItem=${updItem%?};
- ;;
- 2)
- # The fix for the known whitespace issue did not work. Reset the variable back
- # to its original value for additional retries in case the file was locked.
- $updItem="$tmpItem"
- sleep 1s
- ;;
- esac
- if [ $curRetry -ge $maxRetries ]; then
- echo -e "\e[91m\e[1mERROR!\e[0m Maximum retry limit reached. Ownership of" 2>&1 | tee -a $TMPLOG
- echo -e "\e[34m\e[1m${updItem}\e[0m has \e[1mNOT\e[0m been changed." 2>&1 | tee -a $TMPLOG
- # Set the wasUpdated flag to 1 to prevent the loop from executing again.
- wasUpdated=1
- fi
- else
- echo -e " \e[32m\e[1mSuccess!\e[0m Enforced owner: \e[35m\e[1m${DIROWNER[$curID]}\e[0m, group: \e[104m\e[1m${DIRGROUP[$curID]}\e[0m." 2>&1 | tee -a $TMPLOG
- # Update was successful so change the wasUpdated flag to 2 to prevent executing again
- # and sets the flag to run the permissions mask on the new item and set the ownerFound
- # flag to 1 to indicate the correct owner and group have been identified and applied.
- wasUpdated=2
- ownerFound=1
- fi
- if [[ $wasUpdated -eq 2 && $ENABLEMASK -eq 1 && $isBasePath -eq 0 ]]; then
- # Ownership and group were successfully changed, and enable mask is turned on, so set permissions
- # if the item wasn't created in the base (root) path
- echo "Permissions Enforcement" 2>&1 | tee -a $TMPLOG
- sudo chmod "$USEMASK" "${updItem}" 2>&1 | tee -a $TMPLOG
- if [ $? -ne 0 ]; then
- echo -e "\e[91m\e[1mERROR!\e[0m Failed to set permissions on:" 2>&1 | tee -a $TMPLOG
- echo -e " \e[34m\e[1m${updItem}\e[0m." 2>&1 | tee -a $TMPLOG
- else
- echo -e " \e[32m\e[1mSuccess!\e[0m Permissions set to \e[7m${USEMASK}\e[0m." 2>&1 | tee -a $TMPLOG
- fi
- fi
- done
- # ASSIGN OWNER GROUP - END
- fi
- # If the owner was identified, set the DIRID to the DIRCT VALUE+1 to stop script from searching other paths
- if [ $ownerFound -eq 1 ]; then
- DIRID=$((DIRCT+1))
- fi
- # Increase the DIRID by 1 to check the next record. If the owner was already found, it will cause the DIRID
- # to be a value of 2 higher than the DIRCT value, ensuring the loop stops when the owner is identified.
- DIRID=$((DIRID+1))
- isBasePath=0
- done
- ;;
- # CREATE DETECTED - END
- esac
- LOG_CLEAN_OUTPUT
- done
- }
- # ENFORCEMENT FUNCTION - END
- # ==========================================================================================================
- # RESTART ENFORCEMENT FUNCTION - START
- RESTART_ENFORCE()
- {
- # Check the NOKILL option before restarting.
- if [[ $NOKILL -lt 1 ]]; then
- # NOKILL is NOT active, so restart
- echo -e "\e[34m-------------------------------------------------------------\e[0m" 2>&1 | tee -a $TMPLOG
- TIMESTAMP newline
- echo -e "\e[96m\e[1m$SCRIPT_VER will restart enforcement in $RESTARTDELAY seconds.\e[0m" 2>&1 | tee -a $TMPLOG
- sleep "${RESTARTDELAY}"s
- echo -e "\e[34m-------------------------------------------------------------\e[0m" 2>&1 | tee -a $TMPLOG
- TIMESTAMP
- echo -e "\e[96m\e[1mRestarting enforcement now.\e[0m" 2>&1 | tee -a $TMPLOG
- # Call the KILL_INOTIFY function to close any old running script and inotifywait instances
- KILL_INOTIFY
- # Rescan folders for new user folder to enforce then restart enforcement
- SCANFOLDERS
- ENFORCEMENT
- else
- echo -e "The \e[42m\e[1m-nokill\e[0m option was specified, which prevents" 2>&1 | tee -a $TMPLOG
- echo "killing any running processes. This prevents the script from" 2>&1 | tee -a $TMPLOG
- echo "properly restarting internal functions automatically, which is" 2>&1 | tee -a $TMPLOG
- echo "required to establish enforcement on new items. Please exit and" 2>&1 | tee -a $TMPLOG
- echo "restart the script to manually enable enforcement on new items" 2>&1 | tee -a $TMPLOG
- echo "created in the root of the user tree." 2>&1 | tee -a $TMPLOG
- fi
- LOG_CLEAN_OUTPUT
- }
- # RESTART ENFORCEMENT FUNCTION - END
- # ==========================================================================================================
- # KILL_INOTIFY FUNCTION - START
- KILL_INOTIFY()
- {
- # NOKILL CHECK - START
- if [[ $NOKILL -lt 1 && $TESTRUN -ne 1 ]]; then
- # NOKILL is NOT ENABLED and NOT A TEST RUN - So issue KILL command(s) if needed
- echo -e "\e[93m=======================================================================\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[93m\e[1m$SCRIPT_VER - Running Instances Check\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[93m=======================================================================\e[0m" 2>&1 | tee -a $TMPLOG
- TIMESTAMP newline
- echo -e "\e[93mChecking for previous running instances of the script.\e[0m" 2>&1 | tee -a $TMPLOG
- # $PPID - Parent Process ID, $$ - Process ID, $! - Last background task Process ID
- curPID=$$
- # PID Log paths - Used to store PIDs of script instances to try and clean up
- # any left-behind processes from previous or existing runs so that (hopefully)
- # only one instance of the script remains active.
- logPath_CurPID="${SYS_TMP_PATH}/.${MYNAME}_ppid_cur"
- logPath_OldPID="${SYS_TMP_PATH}/.${MYNAME}_ppid_old"
- # Define local variables
- logRead_CurPID=""
- logRead_OldPID=""
- oldPid_Parent=""
- kill_PID_old=0
- kill_Error=0
- # PPID CHECK - START
- if [ ! -f "${logPath_CurPID}" ]; then
- # no existing ppid log exists, so store the current id in the file
- echo "${curPID}" > "${logPath_CurPID}"
- else
- # ppid log file exists, check that the value in the log file matches the ppid of the current instance of the script.
- logRead_CurPID=$( cat "$logPath_CurPID" )
- # Current PID matches the Current PID Identified in the current PID log
- if [ $curPID -eq $logRead_CurPID ]; then
- kill_PID_old=0
- echo -e "\e[93mOnly the current script instance PID was found.\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[93mAttempting to kill running inotifywait instance(s).\e[0m" 2>&1 | tee -a $TMPLOG
- else
- # current log file ppid does NOT match the ppid of the current script instance
- # copy the existing current ppid log into the old ppid log then replace the
- # PID in the current ppid log
- echo "${logRead_CurPID}" >> "${logPath_OldPID}"
- echo "${curPID}" > "${logPath_CurPID}"
- # Set the flag to trigger the kill old pids since we know at least one old pid exists to check for
- kill_PID_old=1
- fi
- # kill_PID_old ENABLED - START
- if [ $kill_PID_old -eq 1 ]; then
- # LOOP THROUGH OLD PIDs - START
- echo -e "\e[93mCycling through known previous PIDs.\e[0m" 2>&1 | tee -a $TMPLOG
- while read line
- do
- logRead_OldPID=($line)
- echo -e "\e[93mPID Found: \e[1m$logRead_OldPID\e[0m" 2>&1 | tee -a $TMPLOG
- # KILL OLD PPID - START
- # check if the old PPID is still running by requesting its parent process
- oldPid_Parent=$( ps -o ppid= "$logRead_OldPID" )
- if [ ! -z "${oldPid_Parent}" ]; then
- # oldPid_Parent was NOT empty, so the old process is still running as a parent was able to be identified
- if [ $DEBUG -eq 1 ]; then echo -e "\e[45m\e[1mDEBUG:\e[0mThe value of oldPid_Parent is: ${oldPid_Parent}"; fi
- echo -e "\e[93mA previous instance is still running \e[1m(${logRead_OldPID})\e[0m\e[93m.\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[93mAttempting to terminate process \e[1m(${logRead_OldPID})\e[0m\e[93m.\e[0m" 2>&1 | tee -a $TMPLOG
- kill $logRead_OldPID
- if [ $? -eq 0 ]; then
- echo -e "\e[93mSuccessfully terminated process \e[1m(${logRead_OldPID})\e[0m\e[1m.\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[93mGiving system time to terminate related inotifywait instances."
- sleep 5s
- else
- echo -e "\e[91m\e[1mERROR!\e[0m \e[93mScript was unable to terminate process \e[1m(${logRead_OldPID})\e[0m\e[93m.\e[0m" 2>&1 | tee -a $TMPLOG
- kill_Error=1
- fi
- else
- # The old PPID is NOT running
- echo -e "\e[93mThe previous process \e[1m(${logRead_OldPID})\e[0m\e[93m is not running.\e[0m" 2>&1 | tee -a $TMPLOG
- fi
- # KILL OLD PPID - END
- done < $logPath_OldPID
- # LOOP THROUGH OLD PIDs - START
- # Finished looping through old script PIDs and killing them
- # REMOVE OLD PPID LOG
- if [ $kill_Error -ne 1 ]; then
- # Killed all known old processes so remove the old pid log file
- sudo rm $logPath_OldPID
- else
- # One or more processes were not killed. Do NOT delete the old pid log file
- echo -e "\e[93mThis is not a fatal error so continuing enforcement. Be aware\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[93mthat if the process(es) that were not able to be stopped are\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[93mstill running and may need a full system reboot to clear.\e[0m" 2>&1 | tee -a $TMPLOG
- fi
- # else
- # Old PPID is not active
- fi
- # kill_PID_old ENABLED - END
- fi
- # PPID CHECK - END
- if [ $ALLOW_MULTIPLE -eq 0 ]; then
- # ALLOW_MULTIPLE is DISABLED (0) so kill other inotifywait instances
- # Check for unknown instances of inotifywait. If any still exist, send kill command
- checkInotifyUnknown=$(pgrep inotifywait)
- if [ ! -z $checkInotifyUnknown ]; then
- # Unknown inotifywatch processes were found running. May be orphans so use killall
- echo -e "\e[93mOne or more inotifywait processes are still running. Attempting\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[93mto stop by sending a killall to try and clean these up as they are\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[93mlikely either orphans or were launched from the currently running\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[93mscript instance.\e[0m" 2>&1 | tee -a $TMPLOG
- killall -9 inotifywait
- if [ $? -ne 0 ]; then
- TIMESTAMP newline
- echo -e "\e[91m\e[1mERROR!\e[0m \e[93mFailed to kill one or more running inotifywait processes.\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[93mIdentified PID(s):\e[0m" 2>&1 | tee -a $TMPLOG
- echo $checkInotifyUnknown 2>&1 | tee -a $TMPLOG
- echo -e "\e[93mAttempt to manually kill each process identified. If the kill command\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[93mcontinues to fail, you should restart the system.\e[0m" 2>&1 | tee -a $TMPLOG
- else
- # All identified unknown inotifywait instances were killed
- echo -e "\e[93mSuccessfully stopped all identified inotifywait processes.\e[0m" 2>&1 | tee -a $TMPLOG
- fi
- else
- # No running inotifywait processes were found running.
- echo -e "\e[93mNo inotifywait processes were found running.\e[0m" 2>&1 | tee -a $TMPLOG
- fi
- else
- # ALLOW_MULTIPLE is ENABLED (1), so do NOT kill other inotifywait
- echo -e "\e[93m\e[1mALLOW MULTIPLE\e[21m is \e[1mENABLED\e[21m.\e[0m"
- echo -e "\e[93mUnknown inotifywait processes will \e[1mNOT\e[21m be stopped.\e[0m" 2>&1 | tee -a $TMPLOG
- fi
- else
- # NOKILL is ENABLED or TESTRUN is ON - So DO NOT ISSUE KILL Commands
- if [ $NOKILL -eq 1 ]; then
- echo -e "\e[93m\e[1mNOKILL\e[0m\e[93m is enabled. Kill commands were \e[1mNOT\e[21m issued.\e[0m"
- fi
- if [ $TESTRUN -eq 1 ]; then
- echo -e "\e[93m\e[1mTEST RUN\e[0m\e[93m - Since this is a test run, kill commands were\e[0m"
- echo -e "\e[93mNOT issued.\e[0m"
- fi
- fi
- # NOKILL CHECK - END
- LOG_CLEAN_OUTPUT
- }
- # KILL_INOTIFY FUNCTION - END
- # ==========================================================================================================
- # LOG_CLEAN_OUTPUT FUNCTION - START - The purpose of this function is to clean up the formatting escape sequences
- # from the log file. When triggered, it exports the temporary logfile into the
- # current day's log file, cleaning up the output.
- LOG_CLEAN_OUTPUT()
- {
- if [ $ENABLELOG -eq 1 ]; then
- # Logging is enabled
- # Write temporary log data to daily log, removing text formatting escape sequences
- LOGFILE="${LOGFILEPATH}/${MYNAME}_`date +\%Y\%m\%d`.log"
- if [ -f $TMPLOG ]; then
- # TMPLOG Exists so clean up output and write it to the main log
- cat $TMPLOG | sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,3})?)?[m|K]//g" >> $LOGFILE
- if [ $? -eq 0 ]; then
- # Successfully flushed TMPLOG data to main LOGFILE so delete TMPLOG to clear it
- sudo rm $TMPLOG
- #else
- fi
- # else
- # TMPLOG doesn't exist, so there's nothing to write to the main log
- fi
- # else
- # Logging is disabled, so no need to touch any files as log output was redirected to /dev/null.
- fi
- }
- # LOG_CLEAN_OUTPUT FUNCTION - END
- # ==========================================================================================================
- # FUNCTIONS - END
- # ==========================================================================================================
- # SCRIPT START
- # SCRIPT VARIABLES - START
- # MYNAME - Assigns the filename used to launch the script to MYNAME to support
- # multiple instances, as this gives each uniquely named copy of the script its
- # own unique log file and PID tracking. This is an attempt at allowing multiple
- # instances of the script to watch multiple different root paths with different
- # settings.
- MYNAME=${0##*/}
- # SYS_TMP_PATH - Verify it is not empty
- if [ -z $SYS_TMP_PATH ]; then
- # SYS_TMP_PATH value was not found (empty), use default /tmp path
- SYS_TMP_PATH="/tmp"
- fi
- # ALLOW_MULTIPLE
- if [ -z $ALLOW_MULTIPLE ]; then
- # No value was defined. Default to 0 (DISABLED)
- ALLOW_MULTIPLE=0
- fi
- # LOGFILE - path and name, uncluding timestamp
- if [ $ENABLELOG -eq 1 ]; then
- TMPLOG="${SYS_TMP_PATH}/.tmp_${MYNAME}_`date +\%Y\%m\%d`.log"
- else
- TMPLOG="/dev/null"
- fi
- # LOGGED IN USERS DURING DELETE
- if [ -z $SHOW_USERS_ON_DELETE ]; then
- # If a value isn't defined, then default to showing the logged
- # in users at the time of file deletions.
- SHOW_USERS_ON_DELETE=1
- fi
- # Send startup notice to the console
- echo -e "\e[96m\e[1m=======================================================================\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e -n "\e[96m\e[1m$SCRIPT_VER is starting.\e[0m " 2>&1 | tee -a $TMPLOG
- TIMESTAMP newline
- echo -e "\e[96m\e[1m=======================================================================\e[0m" 2>&1 | tee -a $TMPLOG
- # DEFINE ADDITIONAL VARIABLES
- SETMASK=0
- SETPRESERVE=0
- SETTEST=0
- SETNOKILL=0
- NOMASK=0
- DEBUG=0
- # SCRIPT VARIABLES - END
- # CHECK FOR ARGUMENTS - START
- while [[ "$1" != "" ]]; do
- case $1 in
- -nomask)
- # Note: NOMASK is just used to identify if this was triggered from the command line, ENABLEMASK is the
- # actual value used by the script to determine if masking is on or off.
- NOMASK=1
- ENABLEMASK=0
- if [ $DEBUG -eq 1 ]; then echo -e "\e[45m\e[1mDEBUG:\e[0m The -nomask argument was detected"; fi
- # Check if SETMASK has been set and trigger error since they can't be used together
- if [ $SETMASK -eq 1 ]; then
- echo -e "\e[91m\e[1mERROR!\e[0m You can not use \e[42m\e[1m-setmask\e[0m and \e[42m\e[1m-nomask\e[0m together." 2>&1 | tee -a $TMPLOG
- echo "$SCRIPT_VER has terminated." 2>&1 | tee -a $TMPLOG
- LOG_CLEAN_OUTPUT
- exit 1;
- fi
- # Check if TESTRUN has been set and notify that nomask is not needed. Non-fatal
- if [ $TESTRUN -eq 1 ]; then
- echo -e "\e[93m\e[1mNOTICE:\e[0m You do not need to specify the \e[42m\e[1m-nomask\e[0m argument when using \e[42m\e[1m-testrun\e[0m." 2>&1 | tee -a $TMPLOG
- fi
- ;;
- -setmask=*)
- # Note: SETMASK is just used to identify if this was triggered from the command line, ENABLEMASK turns masking
- # on (1) or off (0), USEMASK is the mask value being used by the script
- if [ $DEBUG -eq 1 ]; then echo -e "\e[45m\e[1mDEBUG:\e[0m The -setmask argument was detected."; fi
- SETMASK=1
- ENABLEMASK=1
- USEMASK=${1:9}
- if [ $DEBUG -eq 1 ]; then echo -e "\e[45m\e[1mDEBUG:\e[0m The -setmask= argument captured is: ($USEMASK)"; fi
- # Check if NOMASK is has been set and trigger error since they can't be used together
- if [ $NOMASK -eq 1 ]; then
- echo -e "\e[91m\e[1mERROR!\e[0m You can not use -setmask and -nomask together." 2>&1 | tee -a $TMPLOG
- echo "$SCRIPT_VER has terminated." 2>&1 | tee -a $TMPLOG
- LOG_CLEAN_OUTPUT
- exit 1;
- fi
- ;;
- -preserve)
- SETPRESERVE=1
- PRESERVE=1
- if [ $DEBUG -eq 1 ]; then echo -e "\e[45m\e[1mDEBUG:\e[0m The -preserve argument was detected"; fi
- ;;
- -testrun|-test)
- SETTEST=1
- TESTRUN=1
- if [ $DEBUG -eq 1 ]; then echo -e "\e[45m\e[1mDEBUG:\e[0m The -testrun argument was detected"; fi
- # Check if NOMASK has been set and notify that nomask is not needed for testrun. Non-fatal
- if [ $NOMASK -eq 1 ]; then
- echo -e "\e[93m\e[1mNOTICE:\e[0m You do not need to specify the \e[42m\e[1m-nomask\e[0m argument when using \e[42m\e[1m-testrun\e[0m." 2>&1 | tee -a $TMPLOG
- fi
- ;;
- -nokill)
- SETNOKILL=1
- NOKILL=1
- if [ $DEBUG -eq 1 ]; then echo -e "\e[45m\e[1mDEBUG:\e[0m The -nokill argument was detected"; fi
- ;;
- -delay=*)
- RESTARTDELAY=${1:7}
- if [ $DEBUG -eq 1 ]; then echo -e "\e[45m\e[1mDEBUG:\e[0m The -delay argument was used, captured delay: ($RESTARTDELAY)"; fi
- ;;
- -allowmulti)
- ALLOW_MULTIPLE=1
- ;;
- -viewlog)
- echo "Displaying the most recent log file."
- echo
- cat $LOGFILE
- if [ $? -ne 0 ]; then
- echo "$LOGFILE was not found."
- echo "The script only checks for logs with today's date. If the system has been up"
- echo "for a while, the script may not have had to update any permissions or ownership"
- echo "today. Use 'pidof inotifywait' to make sure the script is still running."
- # else
- # Logfile was found and displayed.
- fi
- echo "Responded to -viewlog request." >> $TMPLOG
- LOG_CLEAN_OUTPUT
- exit 0;
- ;;
- --help)
- echo "If you run $SCRIPT_VER without any arguments, it will"
- echo "use the values set in the USER-DEFINED VARIABLES section of the script."
- echo "These settings can be overridden by using any of these options at the"
- echo "command line."
- echo
- echo -e "Useage: \e[1mfolder-owner-enforcer <options>\e[0m"
- echo
- echo -e " \e[4mOption\e[0m \e[4mDescription\e[0m"
- echo
- echo -e " \e[1m-setmask=NNN\e[0m Sets the value of NNN as the mask to enforce\e[0m"
- echo -e " on the user folders. You can define any valid\e[0m"
- echo -e " chmod mask.\e[0m"
- echo
- echo -e " \e[1m-nomask\e[0m Disables permissions mask enforcement.\e[0m"
- echo -e " Permissions will not be enforced on ANY\e[0m"
- echo -e " items.\e[0m"
- echo
- echo -e " \e[1m-preserve\e[0m Preserves ownership and permissions on\e[0m"
- echo -e " all existing files and folders, and only\e[0m"
- echo -e " enforces ownership (and permissions if\e[0m"
- echo -e " masks are enabled) on NEW items.\e[0m"
- echo
- echo -e " \e[1m-nokill\e[0m Prevents the script from issuing kill commands.\e[0m"
- echo -e " This also prevents the script from restarting\e[0m"
- echo -e " when new folders are detected that require a\e[0m"
- echo -e " restart to establish enforcement on the new\e[0m"
- echo -e " folder. This should ONLY BE USED IF YOU ARE\e[0m"
- echo -e " USING INOTIFYWAIT FOR MONITORING OTHER FOLDERS.\e[0m"
- echo
- echo -e " \e[1m-allowmulti\e[0m Allows multiple inotifywait instances so the\e[0m"
- echo -e " script can be launched to enforce different\e[0m"
- echo -e " settings for different root folders. Note that\e[0m"
- echo -e " each instance should be a separately named copy\e[0m"
- echo -e " of the script.\e[0m"
- echo
- echo -e " \e[1m-delay=NN\e[0m Sets the value of NN to use as the delay when\e[0m"
- echo -e " the script automatically restarts. This setting\e[0m"
- echo -e " is ignored when using the -nokill option. The\e[0m"
- echo -e " purpose is to give administrators enough time to\e[0m"
- echo -e " set ownership and group on new folders created in\e[0m"
- echo -e " the root enforcement folder.\e[0m"
- echo
- echo -e " \e[1m-test\e[0m The -test and -testrun options allow you to run the\e[0m"
- echo -e " \e[1m-testrun\e[0m script without actually applying or enforcing any\e[0m"
- echo -e " settings. It simply identifies the folders that would\e[0m"
- echo -e " be monitored and the settings that would be enforced\e[0m"
- echo -e " if this were not a test run, then prints them to the\e[0m"
- echo -e " screen before exiting. Useful to view your configuration\e[0m"
- echo -e " settings before applying enforcement."
- echo
- echo -e " \e[1m-viewlog\e[0m This option reads the current day's log to the terminal.\e[0m"
- echo
- echo -e " \e[1m--help\e[0m Displays this help message."
- echo
- echo "Responded to --help request." >> $TMPLOG
- LOG_CLEAN_OUTPUT
- exit 0;
- ;;
- *)
- # Invalid argument
- echo -e "\e[91m\e[1mERROR!\e[0m Invalid argument was detected" 2>&1 | tee -a $TMPLOG
- echo "$SCRIPT_VER has terminated." 2>&1 | tee -a $TMPLOG
- LOG_CLEAN_OUTPUT
- exit 1;
- ;;
- esac
- shift
- done
- # CHECK FOR ARGUMENTS - END
- # =======================================================
- # Sleep for 5 seconds to let the system finish loading before validating settings
- echo -e "\e[96m\e[1mInitializing. Please wait...\e[0m"
- sleep 5
- # =======================================================
- # VALIDATE SETTINGS - START
- # Identify the settings (and whether they were started by command line or defined in the script)
- # Then display messages to inform the user of the settings so they can confirm the script is
- # using the options they wanted
- echo -e "\e[96m\e[1m$SCRIPT_VER\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e "\e[1mEnforcement Settings:\e[0m" 2>&1 | tee -a $TMPLOG
- # USEMASK - START
- if [[ ! -z $USEMASK ]]; then
- # Check the first two characters of the USEMASK value as a basic
- # verification that a correctly formatted mask was specified.
- if [[ $SETMASK -eq 1 ]]; then
- # -setmask command line option message
- echo -e " The \e[1m-setmask\e[0m option was specified at the command line."
- echo -e " This overrides any mask value set in the script."
- echo -e " The mask you have specified is: \e[1m$USEMASK\e[0m." 2>&1 | tee -a $TMPLOG
- fi
- VALIDATEMASK
- fi
- # USEMASK - END
- # VALIDMASK - START - Value of (1) Means the mask has been validated, otherwise assume invalid mask
- if [[ $ENABLEMASK -eq 1 && $VALIDMASK -eq 1 ]]; then
- if [[ $TESTRUN -eq 1 ]]; then
- echo -e " \e[1mPermissions to enforce:\e[0m \e[1mTest Run Mode\e[0m" 2>&1 | tee -a $TMPLOG
- echo " permissions will not be enforced. If enforcement was" 2>&1 | tee -a $TMPLOG
- echo -e " enabled, permissions \e[1m$USEMASK\e[0m would be enforced." 2>&1 | tee -a $TMPLOG
- else
- echo -e " \e[1mPermissions to enforce:\e[0m \e[1m$USEMASK\e[0m" 2>&1 | tee -a $TMPLOG
- fi
- fi
- # VALIDMASK - END
- # ENABLEMASK - START
- if [[ $ENABLEMASK -eq 0 ]]; then
- echo -e " \e[1mMasks Disabled\e[0m" 2>&1 | tee -a $TMPLOG
- echo " Permissions masks are disabled and will not be enforced." 2>&1 | tee -a $TMPLOG
- fi
- # NOMASK - END
- # VALIDATE DELAY - START
- # NOKILL is OFF
- if [ $NOKILL -ne 1 ]; then
- if [ ! -z $RESTARTDELAY ]; then
- # There is a value in RESTARTDELAY and NOKILL is NOT enabled, make sure it's a number, and it's higher than 0
- if [ $RESTARTDELAY -gt 0 ]; then
- # The specified delay is valid
- validDelay=1
- else
- echo -e "\e[91m\e[1mERROR!\e[0m \e[1mRESTARTDELAY\e[0m value is not valid!" 2>&1 | tee -a $TMPLOG
- echo " Must be a number higher than 0." 2>&1 | tee -a $TMPLOG
- echo "$SCRIPT_VER has terminated." 2>&1 | tee -a $TMPLOG
- LOG_CLEAN_OUTPUT
- exit 1;
- fi
- # else
- fi
- if [ $validDelay -eq 1 ]; then
- # There's a value assigned to RESTARTDELAY and it has been verified that it is a valid number
- echo -e " \e[1mRestart Delay:\e[0m \e[1m$RESTARTDELAY seconds\e[0m" 2>&1 | tee -a $TMPLOG
- #else
- fi
- # NOKILL is ON
- else
- echo -e " \e[1mNOKILL\e[0m is \e[1mENABLED\e[0m - Script will \e[1mNOT\e[0m automatically restart."
- echo -e " If new watches need to be established, you will need to restart manually."
- fi
- # VALIDATE DELAY - END
- # TEST RUN - START
- if [ $TESTRUN -eq 1 ]; then
- echo -e " \e[1mTest Run\e[0m is enabled." 2>&1 | tee -a $TMPLOG
- echo -e " When running in \e[1mTest Run Mode\e[0m, enforcement of owner, group, and" 2>&1 | tee -a $TMPLOG
- echo " permssions is disabled. This is useful for testing what settings" 2>&1 | tee -a $TMPLOG
- echo " would be applied without actually enforcing the settings." 2>&1 | tee -a $TMPLOG
- fi
- # TEST RUN - END
- # PRESERVE - START -Preserves existing owner, group and permissions on all existing items
- if [ $PRESERVE -eq 1 ]; then
- echo -e " \e[1mPreserve\e[0m is \e[1mENABLED:\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e " \e[1mOwner\e[0m and \e[1mGroup\e[0m will only be enforced on \e[1mNEW\e[0m items." 2>&1 | tee -a $TMPLOG
- echo " Properties of \e[1mexisting\e[0m items will \e[1mnot\e[0m be changed." 2>&1 | tee -a $TMPLOG
- else
- # Preserve is off so enforcing owner, group and permissions on all existing and new items
- echo -e " \e[1mPreserve\e[0m is \e[1mDISABLED:\e[0m" 2>&1 | tee -a $TMPLOG
- echo -e " \e[1mOwner\e[0m and \e[1mGroup\e[0m will be enforced on \e[1mALL\e[0m new and existing items." 2>&1 | tee -a $TMPLOG
- fi
- # PRESERVE - END
- # NOKILL - START
- if [ $NOKILL -eq 1 ]; then
- echo -e " \e[1mNo Kill\e[0m is enabled." 2>&1 | tee -a $TMPLOG
- echo " Running instances of inotifywait will NOT be killed." 2>&1 | tee -a $TMPLOG
- fi
- # NOKILL - END
- # ALLOW_MULTIPLE -allowmulti
- if [ $ALLOW_MULTIPLE -eq 1 ]; then
- echo -e " \e[1mAllow Multiple\e[0m is enabled." 2>&1 | tee -a $TMPLOG
- echo " Unknown running instances of inotifywait will NOT be killed." 2>&1 | tee -a $TMPLOG
- fi
- # LOGGING - START
- if [ $ENABLELOG -eq 1 ]; then
- echo -e " \e[1mLogging\e[0m is enabled." 2>&1 | tee -a $TMPLOG
- else
- echo -e " \e[1mLogging\e[0m is disabled." 2>&1 | tee -a $TMPLOG
- fi
- # LOGGING - END
- # ROOTPATH CHECK VALUE - START - Checks the ROOTPATH variable for trailing slash, add it if it is missing
- # along with an asterisk (wildcard). Also stores the defined ROOTPATH to the BASEPATH
- # variable (without a trailing slash) for comparative operations later.
- # There is a trailing slash. Remove for storing in BASEPATH, add an asterisk to ROOTPATH
- if [[ ${ROOTPATH} == */ ]]; then
- BASEPATH="${ROOTPATH%/*}"
- ROOTPATH="${ROOTPATH}*"
- else
- # There is no trailing slash. Store ROOTPATH in BASEPATH, then add a trailing slash and asterisk to ROOTPATH
- BASEPATH="${ROOTPATH}"
- ROOTPATH="${ROOTPATH}/*"
- fi
- # CHECK PATH IS VALID
- if ! [ -d "${BASEPATH}/" ]; then
- # ROOTPATH is NOT a directory
- echo -e "\e[91m\e[1mERROR!\e[0m Invalid Path!" 2>&1 | tee -a $TMPLOG
- echo "The path defined as the ROOTPATH variable is not a valid folder. Please check the" 2>&1 | tee -a $TMPLOG
- echo "path assigned to ROOTPATH in the folder-owner-enforcer script." 2>&1 | tee -a $TMPLOG
- echo "$SCRIPT_VER has terminated." 2>&1 | tee -a $TMPLOG
- LOG_CLEAN_OUTPUT
- exit 1;
- fi
- # ROOTPATH CHECK VALUE - END
- # VALIDATE SETTINGS - END
- # ==========================================================================================================
- # RUN SCRIPT FUNCTIONS - START
- # Update the formatting on the current log file
- LOG_CLEAN_OUTPUT
- # Run the KILL_INOTIFY function to terminate any existing running instances of inotifywait
- KILL_INOTIFY
- # Check if this is a test run or not to determine if enforcement should be enabled.
- if [ $TESTRUN -eq 1 ]; then
- # This is a test run, just run the SCANFOLDERS function
- SCANFOLDERS
- else
- # This is not a test run, so scan for folders and enable enforcement.
- SCANFOLDERS
- ENFORCEMENT
- fi
- # RUN SCRIPT FUNCTIONS - END
- # SCRIPT END
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement