tags:

views:

45

answers:

4

Edit - Reworded the question a bit on April 7th to make it clearer.

Current working environment is OSX 10.4.11.

I want to scan a log file for a certain phrase. The log file can NOT be emptied at the start of the script. Thus, the script must scan only changes to the log.

My current script:

#!/bin/sh
  tail -f log.txt | while read line 
do
  if echo $line | grep -q 'LOL CANDY'; then
    echo 'LOL MATCH FOUND'
    exit 0
  fi
done

It works properly in the fact that it will 'LOL MATCH FOUND' immediately after finding 'LOL CANDY', but it will not actually quit the script until there is some other addition to the log AFTER the 'LOL CANDY'. I need it to immediately quit. And although I'm not sure it is specifically related, there is the problem of the "tail -f" staying open forever. Can someone please give me an example that will work without using tail -f?

If you want you can give me a bash script, as OSX can handle sh, bash, and some other shells I think.

A: 
tail -f log.txt | sed -n '/interesting/{
p
q
}'

Basically, read lines without printing anything; when you see something interesting, print the line and quit.

Oh, I see you want no 'tail -f'; that's odd, it should quit when it next needs to write to the pipe. If it never writes to the pipe again, that could be a problem.

I suppose you could do:

tail -f log.txt | sed -n '/interesting/{
p
q
}'
echo "EOF" >> log.txt

That gives it something to echo, so it tries and fails and terminates.

Jonathan Leffler
"it should quit when it next needs to write to the pipe. If it never writes to the pipe again, that could be a problem"Yes, that sounds like it is the problem then. However, your "EOF" solution does not fix the problem; the program behaves exactly the same. Perhaps because the EOF is being appended to the end of a previously read line? I would go ahead and fix this myself, but I'm uncertain as to how to echo a new line.
James
I think `bash` is doing job control slightly differently from the way Bourne or Korn shells used to do it. I had a modestly complex setup, but it appeared that the shell would not prompt again until both ends of the pipeline exited - or maybe it requires the leading element (`tail -f`) to exit. Classically, the exit status of a pipeline is the exit status of the last command, and when it exits, the pipeline is done. I've run into some other issues with bash (code that was working fine for years under non-bash shells) in faintly related areas - and I've not gotten to the bottom of it. Irksome!
Jonathan Leffler
A: 

Are you clearing the log.txt when you launch your script the second time? You may be interpreting that it takes two appearances of your quit-line when actually it only takes one. Because you are using -f, it will only list everything added once you start up your script.

So the first time you tail it you get your wanted line and you quit. You re-launch the script, it will ignore the first instance because it is not going to be inputted into your -f argument to tail. However the next occurrance should quit. If you look into your log you will see two LOL CANDY lines because you are just following the tail and not looking at what is already in the log.

If you wanted your script to die anytime that line appears in the log, you could add this to the beginning of your script.

 #!/bin/sh
  if grep 'LOL CANDY' log.txt; then
   echo 'LOL MATCH FOUND'
   exit 0
  fi

  tail -f log.txt | while read line 
do
  if echo $line | grep -q 'LOL CANDY'; then
    echo 'LOL MATCH FOUND'
    exit 0
  fi
done

Also if you wanted to get rid of the tail -f you could do what I listed in the first instance in an infinite while loop (syntax might be wrong, been a while):

#!/bin/sh
while (1)
do
  if grep 'LOL CANDY' log.txt; then
   echo 'LOL MATCH FOUND'
   exit 0
  fi
done

Of course if your log file gets pretty large then this will eat up a lot of resources and take a lot of time.

bmucklow
The log will NOT be cleared every-time, nor is it possible to do so. I apologize for not stating so in the original question and as far as I can tell this fact negates all of your proposed solutions.
James
A: 

try this

(tail -f  file| awk '/interesting/{print;exit}')
ghostdog74
I've tried this; it runs identical to my own. In other words, there has to be some additional entry in the log AFTER the key-phrase in order for the script to actually quit.Ideas?
James
A: 

I am not quite sure if I understand your question. Anyway, I tried your script, it did not quit on first run. So, How about adding :

pid=`ps -ef | grep "tail -f log.txt" | grep -v grep | awk '{print $2}'`
kill -2 $pid

before exit 0 so that the tail -f exits?

ring bearer
This is what happens when I try that code: ps: illegal option -- f usage: ps [-aACcehjlmMrSTuvwx] [-O|o fmt] [-p pid] [-t tty] [-U user] ps [-L] kill: usage: kill [-s sigspec | -n signum | -sigspec] [pid | job]... or kill -l [sigspec] logout [Process completed]
James
Doesn't look like there is a -f option in the OSX ps I guess.
James
@James this is interesting. I tried the snippet on my macbook pro, with latest snow leopard version. It ran fine!Also, take a look at online man page for OS X http://developer.apple.com/mac/library/DOCUMENTATION/Darwin/Reference/ManPages/man1/ps.1.html, it does have -f option what version are you running?
ring bearer