I wanted to watch a file under OpenBSD to synchronize my PowerDNS database between two hosts.
First, I tried the entr
tool, while it worked, it would usually die after a
few days.
OpenBSD philosophy being that daemon should not be restarted on crash, there is no clean way to restart it if it crashes.
I ended up writing a simple shell script. But as I did, I found a few small gotcha and I think it can make it to the posterity.
Below a fully commented version:
#!/bin/sh
# This is the file I am observing
DB=/var/db/pdns/pdns.sqlite3
# This is the command I run if the file changes, simply rsync wrapper
SYNC=/etc/pdns/sync.sh
# This is this script, to let me invoke it recursively
SELF=$0
# If we are invoked with the watch argument, let's loop forever
if [ "$1" = "watch" ] ; then
# Get the file modified time (OpenBSD format)
TIME0=$(stat -f %m $DB)
while true
do
# Get the time again
TIME1=$(stat -f %m $DB)
# If it changed simply run the command and save the time
if [[ "$TIME0" != "$TIME1" ]]
then
$SYNC
TIME0=$TIME1
fi
# This is the poll time, you can make it shorter, but 10 second is enough
# This part is important, we fork the sleep call to the background, this
# is to ensure that this script will exit immedialy when killed with
# SIGTERM
sleep 10 &
wait $!
done
fi
# If not invoked with the watch argument, invoke again with it in the background
# This acts as a start script
if [ "$1" != "watch" ] ; then
$SELF watch &
exit 0
fi