Using tail -f on a log file with grep in bash script

孤人 提交于 2019-11-30 20:40:51

问题


I'd like to create a script that greps for a specific string in a log file that is being written to. I'd like to take the first result and put that into a variable for later use. This will be used though an SSH connection like so:

ssh 'user@xxx.xxx.xxx.xxx' 'bash -s' < /usr/local/bin/checklog.sh string

The command in a regular terminal

tail -f /var/log/named.log | grep $1 > $var
echo "${var}"

When I try the above method, there's no output


回答1:


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"



回答2:


> $var doesn't do what you think it does.
It redirects the output of the preceding command to a file with name of what $var contains.
To capture the output of a command and put it into a variable, use variableName="$(...)".

var="$(tail -f /var/log/named.log | grep $1)"



回答3:


Thank you all for the input. You helped figure out a better way to do it, using while and tail without -f

werd=$1
var=""
while [ "${var}" == "" ]
do
var=$(tail -1 /var/log/named.log | grep "${werd}");
done
echo "${var}";

This just reads the last line in the file. Since the file is being written to, the last line changes which is the result I was looking for.



来源:https://stackoverflow.com/questions/30787575/using-tail-f-on-a-log-file-with-grep-in-bash-script

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!