Using a while
loop may work for your situation, but be aware that it's not guaranteed to catch every line of the log file. Consider a situation where the log writer includes one action that writes out two lines:
Something bad just happened:\nError xyz on line 22
It's very likely that your loop will only see the second line when it performs the tail -1
action.
Not only that, but the while loop implementation means your spinning the CPU in a loop, constantly firing off tail
commands (take a look at top
while the while
implementation runs, versus a tail -f
).
This question has some good suggestions if you just want to stop monitoring once the pattern is matched. (Note the concerns of the tail process hanging around.)
This monstrosity is probably not optimal, but it catches every line, uses minimal CPU while waiting for new lines, terminates the tail when it's done, and gives you the flexibility to write in some extra logic (like performing actions based on different matched patterns):
watchPattern=$1
logFile=/var/log/named.log
logLine=""
while read -r logLine ; do
#Do we have a match?
if [[ "$logLine" == *"$watchPattern"* ]] ; then
#Confirmation message, written to console (for example, not needed)
echo "Found a match."
#Kill off the tail process (a bit of a hack that assumes one at a time)
kill $(ps -eo pid,command | awk -v pattern="tail -fn0 $logFile" '$0 ~ pattern && !/awk/ {print $1}')
#Get out of here
break
fi
done< <(exec tail -fn0 "$logFile")
#logLine will be the matched value
echo "match = $logLine"