Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm trying to write a command to test that data is written to a file. My first approach was:

  1. Start reading in the background.
  2. Write some data to the file.
  3. Wait for the reader to find a result.
  4. Repeat indefinitely to see if there's a timing issue.

In script form:

while true
do
    grep -q foo <(tail -n0 -f /var/log/syslog) &
    logger foo && logger line && wait
done

(the logger line command is to avoid last message repeated N times lines in the file)

This version will typically loop a once or twice before getting stuck at the wait command, so it looks like tail didn't have time to start reading before logger foo had written to the file.

What is the best way to guarantee that tail is reading before continuing? These workarounds are not ideal:

  • Pause before logger (won't work in the case of slow file systems)

        sleep 1 && logger foo && logger line && wait
    
  • Start a second reader, and assume that the first one has started reading by the time the second has been shown to. This looped a few thousand times before getting stuck:

        grep -q foo <(tail -n0 -f /var/log/syslog) &
        grep -q bar <(tail -n0 -f /var/log/syslog) &
        while kill -0 $!
        do
            logger bar
            logger line
        done
        logger foo && logger line && wait
    
share|improve this question
    
Perhaps you could tell us more about what you're really trying to do. This example seems overly contrived and pedantic. If you want to know if arbitrary data has been written to an arbitrary file you should just use stat to see if the size has changed. More bytes means more data. So your initial premise is solved very easily. This looks like a classic X/Y problem. –  bahamat Jan 17 '13 at 16:36
    
I'm trying to check whether my process (logger) is writing to a world-writable log file. So stat is not the solution. –  l0b0 Jan 17 '13 at 18:50
    
That's the Y, not the X. You have some problem, which you have yet to tell us about, that you think the right way to solve that is to snoop the file to see if it contains the content you want. You have a number of problems. 1st, syslog is not world writable, sysklogd (or rsyslogd) writes it. 2nd syslog makes no guarantee about how frequently it flushes buffers. Your message is sent, syslog got it. You're just not waiting for the I/O. It looks to me like what you really need is to understand syslog better. Why not ask about that? –  bahamat Jan 17 '13 at 20:48
add comment

1 Answer

Here's one way, re-using the reader after establishing that it is indeed reading:

while true
do
    exec 3<> myfifo
    tail -n0 -f /var/log/syslog >&3 &
    tailproc=$!
    while ! grep -q start <&3
    do
        logger start
        logger line
    done
    grep -q end <&3 &
    logger end
    logger line
    wait $!
    exec 3<&-
    exec 3>&-
    kill $tailproc
done

Since the writer is blocked while nobody is reading (between the first and the second grep commands) it shouldn't be possible for the second grep to miss out on the next line.

This has been running for a few tens of thousands of iterations (based on the process IDs in the output) without getting stuck.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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