How to trigger a script to run after the rsyncdaemon received file changes to a certain folder

rsyncscripting

I have several servers where rsyncd is running. I don't use an ssh tunnel, but the native rsync protocol. One folder of the synchronized files contains the files that should form an iso image.
Whenever a file in that folder is uploaded (pushed from remote to this server), it shall recreate the iso file automatically. Ideally only file content or size changes should trigger this because I want to show the date of the last change of the iso inside a webpage where the users can download and burn it.

Because the iso is large I want to create it on each server if just one file changes. I don't want to sync the iso itself

Best Answer

This is more a response to Gilles but I wanted to format a little code; a slick way you can do the monitoring of the changed files is to store a md5sum of md5sums of the directory, ala:

find /path/to/iso/data/ -type f -exec md5sum {} + | awk '{print $1}' | sort | md5sum | awk '{print $1}'

...which gives you output of the type:

b843afc89097f0abc062e0d0e14d480b

If you save that on each iteration of your cron, it's a pretty quick and effective way to determine if contents have changed on the target. You could even build a wrapper around the xinetd rsync daemon; replace the call to the binary in /etc/xinetd.d/rsync:

server          = /usr/bin/rsync

...with a script:

server          = /path/to/script.sh

And then in your script compare and do the deed every time the daemon exits with a valid 0 status. That's way more automated than a cron job, with the benefit it only runs if you code it to rsync exit 0. Something like... (psuedo code here):

#!/bin/sh

/usr/bin/rsync "$*"

if [ $? -eq 0 ]; then
  OLDVALUE=`cat /var/cache/isodata.txt`
  NEWVALUE=`find /path/to/iso/data/ -type f -exec md5sum {} + | awk '{print $1}' | sort | md5sum | awk '{print $1}'`
  if [ ${OLDVALUE} != ${NEWVALUE} ]; then
    -- run ISO making code --
    echo ${NEWVALUE} > /var/cache/isodata.txt
  fi
fi

That's the general idea to start with.