Skip to content
Snippets Groups Projects
Commit d2de5025 authored by Hahn Axel (hahn)'s avatar Hahn Axel (hahn)
Browse files

import shellscript

parent 1359fa87
Branches
No related tags found
No related merge requests found
#!/bin/bash
# ======================================================================
#
#
# T R I G G E R C O M M A N D O N A F I L E C H A N G E
#
#
# A Shell script that watches a given file or multiple files.
# If the file changes then a given command will be exxecuted.
# It loops permanently; you need to stop it by Ctrl + C and/ or can
# use it as systemd watcher daemon.
#
# It uses stats for wide compatibility but prefers inotifywatch to
# check a file change.
#
# licence: GNU GPL 3.0
#
# ----------------------------------------------------------------------
# 2019-10-14 v1.0 <axel.hahn@iml.unibe.ch> first basic version
# ======================================================================
# ----------------------------------------------------------------------
# CONFIG
# ----------------------------------------------------------------------
bDebug=0
iSleep=5
sCommand=
sWatchFile=
sMode=
# ---- below are some internal variables
sVersion=1.0
# ----------------------------------------------------------------------
# FUNCTIONS
# ----------------------------------------------------------------------
# show help
function showHelp(){
cat <<ENDOFHELP
HELP:
This script checks the change of a given file and triggers
a command if it changes
PRAMETERS:
-c [command]
command to execute on a file change
-f [filename(s)]
filenames to watch; separate multiple files with space and put all in quotes
-h
show this help
-i
force inotifywait command
-s
force stats command
-v
verbose mode; enable showing debug output
-w [integer]
for stats mode: wait time in seconds betweeen each test or on missing file; default: 5 sec
EXAMPLES:
`basename $0` -f /home/me/touchfile.txt -c "ls -l"
watch touchfile.txt and make a file listing on change
`basename $0` -f "/home/me/touchfile.txt home/me/touchfile2.txt" -c "ls -l"
watch touchfile.txt and touchfile2.txt
`basename $0` -f /home/me/touchfile.txt -s -w 10 -c "ls -l"
watch touchfile.txt every 10 sec with stats and make a file listing on change
ENDOFHELP
}
# write debug output ... if debug is enabled only
#
# global (bool) $bDebug
# param string text message to show
function wd(){
if [ $bDebug -ne 0 ]; then
echo "[`date`] DEBUG " $*
fi
}
# list watched files
#
# global (string) filename(s) to watch
function listFiles(){
echo
echo ">>>>> watched files"
ls -ld ${sWatchFile} 2>&1
}
# for stats: helper to get current file status
#
# global (string) $sWatchFile
function getFilestatus(){
for myfile in ${sWatchFile}
do
stat -c "%F %n | perms: %A; user %u (%U) group %g (%G) | size: %s byte | last modification %y" "${myfile}" 2>&1
done
}
# for stats: inititalize file change detection
#
# global (string) $TmpFile last/ initial file status
# global (string) $sTmpFile2 current file status
function initFilestatus(){
getFilestatus >${sTmpFile}
wd "`cat ${sTmpFile}`"
cp -p ${sTmpFile} ${sTmpFile2}
}
# for stats: compare file status and execute command on change
#
# global (string) $TmpFile last/ initial file status
# global (string) $sTmpFile2 current file status
# global (string) $sCommand command to execute
function compareFilestatus(){
getFilestatus >${sTmpFile2}
wd "`cat ${sTmpFile2}`"
diff ${sTmpFile} ${sTmpFile2}
if [ $? -eq 0 ]; then
wd "No Change"
else
wd "Change detected."
execCommand
if [ $? -eq 0 ]; then
echo Command was successfuil.
echo
wd "Re-Init File status"
initFilestatus
else
echo FAILED.
fi
fi
}
# execute a command; called on a file change
#
# global (string) $sCommand command line to exectute
function execCommand(){
listFiles
echo
echo ">>>>> `date` Executing ${sCommand} ..."
${sCommand}
}
# ----------------------------------------------------------------------
# MAIN
# ----------------------------------------------------------------------
cat <<ENDOFHEAD
____________________________________________________________________________________
T R I G G E R C O M M A N D O N A F I L E C H A N G E
____________________________________________________________________________________
v${sVersion}
ENDOFHEAD
which inotifywait >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo ERROR: the command inotify was not found on your system,
which stat >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo ERROR: the command stat was not found on your system,
exit 2
fi
echo "INFO: enabling compatibility mode with stats command"
sMode=stats
else
echo "INFO: inotifywait command detected"
sMode=inotifywait
fi
if [ $# -eq 0 ]; then
showHelp
exit 0
fi
while getopts ":c: :v :f: :h :i :s :w:" opt
do
case $opt in
\?|h)
showHelp
exit 0
;;
v)
bDebug=1
wd "debug is now ${bDebug}"
;;
c)
sCommand=$OPTARG
wd "command is now ${sCommand}"
;;
f)
sWatchFile=$OPTARG
wd "watch file is now ${sWatchFile}"
;;
i)
sMode=inotifywait
wd "forcing mode with inotifywait command"
;;
s)
sMode=stats
wd "forcing mode with stats command"
;;
w)
typeset -i iSleep=$OPTARG
wd "sleep $iSleep sec"
;;
:)
echo "ERROR: Option -$opt requires an argument." >&2
showHelp
exit 1
esac
done
cat <<ENDOFINFO
checking file [${sWatchFile}]
with command [${sMode}]
with a sleep time of [${iSleep}] seconds
and on change start command [${sCommand}]
...............................................................................
ENDOFINFO
# ----------------------------------------------------------------------
# CHECKS
# ----------------------------------------------------------------------
wd "--- checks"
if [ -z "${sWatchFile}" ]; then
echo ERROR: set a check file with param -f
exit 1
fi
listFiles
if [ $? -ne 0 ]; then
echo "INFO: file ${sWatchFile} (or one of them) does not exist yet"
# echo "ERROR: file ${sWatchFile} (or one of them) does not exist yet"
# exit 1
fi
if [ -z "${sCommand}" ]; then
echo ERROR: set a ${sCommand} with param -s
exit 1
fi
# ----------------------------------------------------------------------
# GO
# ----------------------------------------------------------------------
myset=`echo ${sWatchFile} | sha1sum | cut -f 1 -d " "`
sTmpFile="/tmp/`basename $0`-${myset}-last.tmp"
sTmpFile2="/tmp/`basename $0`-${myset}-current.tmp"
case $sMode in
"inotifywait")
while true; do
listFiles >/dev/null 2>&1
if [ $? -eq 0 ]; then
inotifywait -e attrib -e modify ${sWatchFile} && execCommand
else
wd sleep ${iSleep}
sleep ${iSleep}
echo "WARNING: inotifywait only can notify if all watched files exist. You can use -s to use stats for file detection"
fi
done
;;
"stats")
wd "--- init"
initFilestatus
echo waiting for file changes ...
wd "--- starting loop"
while true; do
wd sleep ${iSleep}
sleep ${iSleep}
compareFilestatus
done
;;
esac
# ----------------------------------------------------------------------
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment