views:

42

answers:

2

I have the following bash script:

tail -F -n0 /private/var/log/system.log | while read line 
do
    if [ ! `echo $line | grep -c 'launchd'` -eq 0 ]; then
        echo 'launchd message'
        exit 0
    fi
done

For some reason, it is echoing launchd message, waiting for a full 5 seconds, and then exiting.

Why is this happening and how do I make it exit immediately after it echos launchd message?

+3  A: 

Since you're using a pipe, the while loop is being run in a subshell. Run it in the main shell instead.

#!/bin/bash

while ...
do
   ...
done < <(tail ...)
Ignacio Vazquez-Abrams
I'm getting a syntax error at the done line...
Chetan
Ah, it was because I was using /bin/sh, stupid me.
Chetan
Invoking bash as sh disables certain features, including process substitution.
Ignacio Vazquez-Abrams
+1  A: 

As indicated by Ignacio, your tail | while creates a subshell. The delay is because it's waiting for the next line to be written to the log file before everything closes.

You can add this line immediately before your exit command if you'd prefer not using process substitution:

kill -SIGPIPE $$

Unfortunately, I don't know of any way to control the exit code using this method. It will be 141 which is 128 + 13 (the signal number of SIGPIPE).

If you're trying to make the startup of a daemon dependent on another one having started, there's probably a better way to do that.

By the way, if you're really writing a Bash script (which you'd have to be to use <() process substitution), you can write your if like this: if [[ $line == *launchd* ]].

Dennis Williamson