Monitoring a file until a string is found

bashgreplogfilestail

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.

Best Answer

A simple POSIX one-liner

Here is a simple one-liner. It doesn't need bash-specific or non-POSIX tricks, or even a named pipe. All you really need is to decouple the termination of tail from grep. That way, once grep ends, the script can continue even if tail hasn't ended yet. So this simple method will get you there:

( tail -f -n0 logfile.log & ) | grep -q "Server Started"

grep will block until it has found the string, whereupon it will exit. By making tail run from it's own sub-shell, we can place it in the background so it runs independently. Meanwhile, the main shell is free to continue execution of the script as soon as grep exits. tail will linger in its sub-shell until the next line has been written to the logfile, and then exit (possibly even after the main script has terminated). The main point is that the pipeline no longer waits for tail to terminate, so the pipeline exits as soon as grep exits.

Some minor tweaks:

  • The option -n0 to tail makes it start reading from the current last line of logfile, in case the string exists earlier in the logfile.
  • You might want to give tail -F rather than -f. It is not POSIX, but it allows tail to work even if the log is rotated while waiting.
  • Option -q rather than -m1 makes grep quit after the first occurrence, but without printing out the trigger line. Also it is POSIX, which -m1 isn't.
Related Question