Triggering scripts to run when a file or folders change is a common advanced task. Recent applications like Dropbox and BitSync have grown from the days of rsync magic, but what about triggering code when a sync occurs. It could be as simple as emailing a photo to your parents once 5 pictures are updated in Dropbox or as advanced as rebuilding a static blog based on content changes of configuration files in a folder. This post focuses on the Linux tool for handling these events that relies on inotify; but there are similar (not covered here) ways on BSD/OSX/Windows too (FSEvents/kqueue).
I ran into this when setting up a Dropbox sync to cause a Grunt process to build a stage server. The Dropbox sync would need to trigger an Assemble.io process to turn Yaml files (that are held in the Dropbox path) into HTML.
Inotify is the systems way to event filesystem changes, but to be able to tap into inotify events it’s easiest to install another daemon called incrond (inotify cron daemon) that abstracts inotify system calls in a manageable way.
Type the following command under RHEL / Fedora / CentOS Linux:
$ sudo yum install incron
Type the following command under Debian / Ubuntu Linux:
$ sudo apt-get install incron
Once you have incron installed, you should configure it. The users needing to take action ( ie. run scripts ) will determine what configuration you will want to use. Begin by taking a look at ‘/etc/incron.conf’ to make global changes to incron. Configurations options should speak for themselves; but here they are to be clear.
- This directory is examined by incrond for system table files.
- This directory is examined by incrond for user table files.
- This file contains users allowed to use incron.
- This file contains users denied to use incron.
- This directory is used for creating a lock avoiding to run multiple instances of incrond.
- This name (appended by ‘.pid’) is used for creating a lock avoiding to run multiple instances of incrond.
- This name or path is used to run as an editor for editting incron tables.
Default:`no editor` is given, system editor used, this option overide this.
To start using incron first add the users you want to the allowed_users (/etc/incron.allow) file. Each line should be a new user. For instance, if you want to run a script as Root ( please don’t for security reasons) then the file would have a single line with ‘root’ on it.
Next, as the user you are wanting to use to watch files, you can do two things. Either edit the appropriate config file or run the command `incrontab -e`. Running the incrontab command can be easier but it’s also, IMO, restrictive.
Create an autoscript user (on linux)
$ sudo -i $ adduser -M -s /dev/null -G "www-data" autoscript $ passwd autoscript *******
Edit the appropriate incron.d config. Add the folders you wish to watch, the commands to watch for and the command to run when they are triggered.
$ vi /var/spool/incron/autoscript $ chown autoscript:autoscript /var/spool/incron/autoscript
Here is what the file could contain
/home/someuser/Dropbox/somefolder/ IN_MODIFY,IN_ATTRIB,IN_CREATE,IN_DELETE /bin/bash /home/someuser/update.sh /home/someuser/Dropbox/somefolder/someinnerfolder/ IN_MODIFY,IN_ATTRIB,IN_CREATE,IN_DELETE /bin/bash /home/someuser/update.sh
You may have noticed in the example above that the folders are not recursive; if you are updating folders frequently, you should automate the creation of the rules for folders to watch. Then you can run your script to update the watching of files. Also, you can target individual files as folders are not required.
In the example above there were some options not talked about yet (IN_###, etc). Those options tell incron what events you are wanting to trigger on. There isn’t a need to list them all here since there are plenty of sites that detail the options (like here).
The final step to this is turning it all on. Probably the easiest part depending on your linux flavor/version
$ service incrond start $ chkconfig incrond on
If chkconfig isn’t installed or used on your system (it’s an older way of doing things) you can check out some other options listed on StackOverflow. Notably, newer linux distributions use SystemD to control daemons.