I am using tail -f to monitor a log file that is being actively written to. When a certain string is written to the log file, I want to quit the monitoring, and continue with the rest of my script.

Currently I am using:

tail -f logfile.log | grep -m 1 "Server Started"

When the string is found, grep quits as expected, but I need to find a way to make the tail command quit too so that the script can continue.

link|improve this question
feedback

4 Answers

up vote 2 down vote accepted

So after doing some testing, I found a quick 1-line way to make this work. It appears tail -f will quit when grep quits, but there's a catch. It appears to only be triggered if the file is opened and closed. I've accomplished this by appending the empty string to the file when grep finds the match.

tail -f logfile |grep -m 1 "Server Started" | xargs echo "" >> logfile \;

I'm not sure why the open/close of the file triggers tail to realize that the pipe is closed, so I wouldn't rely on this behavior. but it seems to work for now.

Reason it closes, look at the -F flag, versus the -f flag.

link|improve this answer
feedback

This will be a bit tricky since you will have to get into process control and signaling. More kludgey would be a two script solution using PID tracking. Better would be using named pipes like this.

What shell script are you using?

For a quick and dirty, one script solution - I would make a perl script using File:Tail

use File::Tail;
$file=File::Tail->new(name=>$name, maxinterval=>300, adjustafter=>7);
while (defined($line=$file->read)) {
    last if $line =~ /Server started/;
}

So rather than printing inside the while loop, you could filter for the string match and break out of the while loop to let your script continue.

Either of these should involve just a little learning to implement the watching flow control you are seeking.

link|improve this answer
using bash. my perl-fu is not that strong, but I'll give this a shot. – Alex Hofsteede Apr 14 '11 at 17:03
Use pipes - they love bash and bash love them. (and your backup software will respect you when it hits one of your pipes) – bmike Apr 27 '11 at 0:57
feedback

Alex i think this one will help you lot.

tail -f logfile |grep -m 1 "Server Started" | xargs echo "" >> /dev/null ;

this command will never give an entry on the logfile but will grep silently...

link|improve this answer
feedback

Try to use inotify (inotifywait)

You set up inotifywait for any file change, then check the file with grep, if not found just rerun inotifywait, if found exit the loop... Smth like that

link|improve this answer
This way, the entire file would have to be rechecked every time something is written to it. Doesn't work well for log files. – grawity Apr 13 '11 at 20:59
1  
Another way is to make two scripts: 1. tail -f logfile.log | grep -m 1 "Server Started" > /tmp/found 2. firstscript.sh& MYPID=$!; inotifywait -e MODIFY /tmp/found; kill -KILL -$MYPID – Evengard Apr 13 '11 at 21:16
I'd love you to edit your answer to show capturing the PID and then using inotifywait - an elegant solution that would be easy to grasp for someone used to grep but needing a more sophisticated tool. – bmike May 10 '11 at 20:47
A PID of what you would like to capture? I can try to make it if you explain a bit more what you want – Evengard May 12 '11 at 20:31
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.