#!/bin/bash
#
#########
# Name:
# pfdirwatch.sh
#
# Version
# 20220402
# Changes to make the display in the terminal window more readable when starting
# w/o "n" or "y". The terminal will roll on, never be cleared, the printout limited
# only by the number of lines available in the terminal window
# 20220207
# added a log in /tmp. It will be deleted each time the machine reboots.
# Each line in the log has a time assigned.
# NOTE: using parentheses in comments sometimes causes error in bash scripts!! It shouldn't but it does.
# Removed parentheses!
# 20220130
# bugfix. (The script only checked for changes in it's own working dir)
# 20220107
# bugfix avoiding unnecessary message
# 20220101
# Original version
#
# Description:
# This script takes two snapshots of the file system and then compares
# them with respect to file time (changes) and existence (deleted or created).
# Since it's rather primitive, changes can happen and vanish between the points
# in time when the snapshots are taken. I use it to check for repetitive tasks
# that changes log files. If changes occur, the task is running.
#
# The time between snapshots are lengthened by the $TIME_TO_READ bcs you need
# to get a glimpse of what happened.
#
# Usage:
# I normally use it like:
# pfdirwatch.sh /home/xhosa/tools/scripts 10 n
# NOTE:It will only work if you are in the same dir as the script when starting it!!
# this will start the script looking like
#+++++++++++++++++++++
#We are in dir /home/xhosa/tools/scripts
#Command: /home/xhosa/tools/scripts/pfdirwatch.sh /home/xhosa/tools/scripts 5 n
#Pid: 598858
#+++++++++++++++++++++
#
#15:46:45
#
# Setting the "n" to a "y" will run it once with only the time displayed and the next
# loop the "y" will have been set to "n" and it will continue like above
#
# Leaving out the "y"/"n" as the third argument makes the program run without the
# header. The terminal display will roll on, the TIME_TO_READ will not limit the time
# you can view changes (they will be readable only limited by the number of lines available
# in the terminal).
#
#########
# --TODO--: another variant of this script, logging to a file and starting tail on it. This way I'd have both live data
# available plus a log!!
#
# change this to what suits you. If you choose /tmp these files will be cleared when restarting
# otherwise you'll have to do that yourself.
TMP="/tmp/pfdirwatch"
FILE="/tmp/pfdirwatch.sh.log"
TIME_TO_READ=6
## creating log
if [ ! -f "$FILE" ]; then
date +%Y-%m-%d_%H:%M:%S >> $FILE
echo -e "Command:" $0 $1 $2 $3 >> $FILE
echo "Logfile: " $FILE
fi
echo -n "." >> $FILE
## if pfdirwatch is a file, remove it, created the dir pfdirwatch
if [[ ! -d $TMP ]]
then # it's a file
if [[ -f $TMP ]]
then
rm $TMP > /dev/null 2&>1
fi
mkdir $TMP
chmod 0750 $TMP
else
## pfdirwatch IS a dir, remove all files in it
for N in `ls -i -A /tmp/pfdirwatch/`; do ((loop++));done
if(( $loop>0 ))
then
rm /tmp/pfdirwatch/* > /dev/null 2&>1
fi
fi
## report on terminal will be readable for this no of seconds.
TIME_TO_READ=4
# asking for the number of arguments to the script, the script itself NOT counted!
if [ $# -lt 2 ]
then echo -e \\n"Usage '$0 folder waitseconds "\\n
exit 1
fi
## checking that argument 1 is a folder
if [ ! -d $1 ]
then
echo "Folder name is false!!"
exit 1
fi
## the "n" as argument 3 will make this report printout on the screen.
if [[ $3 == 'n' ]]
then
clear
echo -e \\n+++++++++++++++++++++
echo "This script's working directory: "`pwd`
echo "Command:" $0 $1 $2 $3
pid=$BASHPID
echo "Pid: "$pid
echo -e +++++++++++++++++++++ \\n
fi
echo `date +%H:%M:%S`
arg3="n"
# find only in this dir (no deeper) only regular files, stat lists %y(modification time) %s(ize) %n(ame)
##find $1 -maxdepth 1 -type f -not \( -name "$pid.lista.txt" -o -name "$pid.listab.txt" \) -exec stat -c '%y %s %n ' {} \;
find $1 -maxdepth 1 -type f -not \( -name "$pid.lista.txt" -o -name "$pid.listab.txt" \) -exec stat -c '%y %s %n ' {} \; > $TMP/$pid.lista.txt
# list looks like:
# < 2011-08-10 12:47:43.000000000 +0200 196 ./tjosan
# > 2011-08-10 12:49:42.000000000 +0200 203 ./tjosan
# > 2011-08-10 12:49:42.000000000 +0200 0 ./124942
# $2 (below) is the measure of time between now and then #the snapshots#, where eventual differences among the files will be
# discovered. This value is a gas pedal, sort of. Comment it or set it to 0 and you'll have live seconds working
# in the printout.
sleep $2
##find $1 -maxdepth 1 -type f -not \( -name "$pid.lista.txt" -o -name "$pid.listab.txt" \) -exec stat -c '%y %s %n ' {} \;
find $1 -maxdepth 1 -type f -not \( -name "$pid.lista.txt" -o -name "$pid.listab.txt" \) -exec stat -c '%y %s %n ' {} \; > $TMP/$pid.listab.txt
# "sed -n '/^[><]/p'>"
# From sed manual: 'By default sed prints all processed input (except input that has been modified/deleted
# by commands such as d). Use -n to suppress output, and the p command to print specific lines.'
# These are decided by "'/^"=from the beginning of the line, "[> or <]"=lines beginning with either, "p"= pls
# print these lines.
# array for diff-data:
diff $TMP/$pid.lista.txt $TMP/$pid.listab.txt|sed -n '/^[><]/p'
diff $TMP/$pid.lista.txt $TMP/$pid.listab.txt|sed -n '/^[><]/p'> $TMP/$pid.diffdata
# checking the block size of the $TMP/$pid.diffdata file
l=`ls -s $TMP/$pid.diffdata|awk '{print $1}'`
# the ls command sys "no blocks are reserved for this file"
#if (( l == 0 ))
#then
#this script| temp dir| time between snapshots
# exec $0 $1 $2 $3
#fi
cat $TMP/$pid.diffdata|awk '{print $6 }'|uniq -d > $TMP/$pid.dupdata
cat $TMP/$pid.diffdata|awk '{print $6 }'|uniq -u $TMP/$pid.dupdata $TMP/$pid.uniqdata|sort
# create indexed array. "-A" means "associative". Here are the snapshots compared.
#
declare -a fs
declare -a ft
for udata in `cat $TMP/$pid.dupdata|awk '{print '$6'}'`
do
loop=0
while read ddata
do
#echo "udata: "$udata
#echo "ddata: "`echo $ddata|awk '{print $6}'`
if [ "$udata" == "`echo $ddata|awk '{print $6}'`" ]
then
fs[$loop]=`echo $ddata|awk '{print $5}'`
# this is the file time:
ft[$loop]=`echo $ddata|awk '{print $3}'`
((loop++))
fi
done < $TMP/$pid.diffdata
if ! [ ${fs[0]} == ${fs[1]} ]
then
echo "Size of $udata has changed: ${fs[0]} => ${fs[1]}";
arg3="y"
echo -e "Size of $udata has changed: ${fs[0]} => ${fs[1]}"; >> $FILE
fi
if ! [ ${ft[0]} == ${ft[1]} ]
then
echo "Filetime of $udata has changed: " `echo ${ft[0]}|cut -c -8` " => " `echo ${ft[1]}|cut -c -8`
arg3="y"
echo -e "Filetime of $udata has changed: " `echo ${ft[0]}|cut -c -8` " => " `echo ${ft[1]}|cut -c -8` >> $FILE
fi
done
for uqdata in `cat $TMP/$pid.uniqdata|awk '{print '$6'}'`
do
loop=0
while read ddata
do
#echo "uqdata: "$uqdata
#echo "ddata: "`echo $ddata|awk '{print $6}'`
if [ "$uqdata" == "`echo $ddata|awk '{print $6}'`" ]
then
DT=`date +%H:%M:%S`
if [ `echo $ddata|awk '{print $1}'` == "<" ]
then
echo ${DT}" Deleted file: "`echo $ddata|awk '{print $6}'`
arg3="y"
echo ${DT}" Deleted file: "`echo $ddata|awk '{print $6}'` >> $FILE
else
echo ${DT}" Added file: "`echo $ddata|awk '{print $6}'`
arg3="y"
echo ${DT}" Added file: "`echo $ddata|awk '{print $6}'` >> $FILE
fi
fi
done < $TMP/$pid.diffdata
done
echo
# if changes are detected you'll have $TIME_TO_READ seconds to read about them
# the ls command sys "no blocks are reserved for this file"
if (( l == 0 ))
then
#this script| temp dir| time between snapshots|"n"
exec $0 $1 $2 $3
fi
sleep $TIME_TO_READ
clear
# and here we go again, looping
exec $0 $1 $2 $3
# - Example code #
# declare g as array and filling it directly from a command. Since there are
# five space-delimited fields in each stat-line and (in the current dir) 150 files
# we'll get 5 * 150 = 750 entries
# echo "1"
# declare -a g=(`find . -maxdepth 1 -type f -not \(-name "$BASHPID.lista.txt"\) -exec stat -c '%y %s %n ' {} \; |sort`)
# - end#
## - Example code #
## - Filling array from a file
# declare -a f
# cnt=0
# while read line
# do
# f[$cnt]=$line
# echo ${f[$cnt]}
# ((cnt++))
# done < lista.txt
## note: this means "${}" = execute, "#" = number of, f[] = the 'f' array, "@" all members of
## so this means: "what is the number of all items in the f-array?"
# echo "Number of f-items: "${#f[@]}
## end #