I'm trying to write a "while true" bash script that responds to events. (It's a webhook for git push notifications, but that's not very relevant at this point.)

I could block, waiting for the next callback, run the build, and then block again, but if I get a callback in the middle of the build, I'd miss that, so instead I'm trying to solve it as follows:

# Build loop, run in the background (see "done &" at the bottom)
while true
    # If last build start is newer than last push do nothing.
    if [ last-build-start -nt last-push ]
        echo "last-build-start newer than last-push. Doing nothing."
        sleep 3
    log "Build triggered $(date)"
    touch last-build-start
    log "Done. Waiting for next trigger..."
done &

# Terminate above loop upon Ctrl+C
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT

# Listen for HTTP requests, do nothing but touch last-push
# to trigger a build in the build loop above.
while true
    # Wait for hook to be called
    echo -e "HTTP/1.1 200 OK\n\n $(date)" \
        | nc -l 8787 -q 1 > /dev/null

    # Trigger new build
    echo "Triggered... touching last-push"
    touch last-push

The problem I'm experiencing is that the build-loop is not always triggered. The touch last-push is executed, but it's just as if another instance of the build loop is kicking in and executing touch last-build-start in a racy way.

Am I accidentally kicking off more than one build loop in the above code? Is there any other silly mistake in the script?

  • 1
    I might misunderstand what you are trying to do but it looks like you could use git post-hook commit: github.com/git/git/blob/master/Documentation/githooks.txt#L142 – hschou Oct 27 '17 at 7:36
  • This is for a bitbucket project. With 0 budget so I don't want to rely on their pipelines. – aioobe Oct 27 '17 at 10:06
  • What OS are you using? I'm trying to test this, but nc complains that -q is an unknown option. – terdon Oct 27 '17 at 10:07
  • Interesting. Ubuntu 16. nc -h says OpenBSD netcat (Debian ...). If it matters, here's what my man page says: -q seconds after EOF on stdin, wait the specified number of seconds and then quit. If seconds is negative, wait forever. – aioobe Oct 27 '17 at 11:06
  • @terdon, I realized I could replace last-push and last-build-start with a dummy file which I create upon a request, and remove upon starting a build. By doing this the race seems to go away. Could it be something specific about checking timestamps the way I'm doing it? – aioobe Oct 27 '17 at 13:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.