Use incron to Trigger Action when File Changes
Written by Guillermo Garron
Date: 2012-03-12 08:30:00 00:00
Introduction
There are some situations, when you need to start an action or run a command when a given file has changed in your file system.
The real life example I have is as follows:
I have a git repository, from where I manage this blog, I have a remote branch of it on the same server, from where Nginx serves this pages.
I also have another remote branch in my Macbook Pro (With the correspondent Time Machine backup). But, I'm a paranoid guy, so I just want more backups. I decided I wanted to backup all my blog files to my Dropbox account.
These are the needed tools:
- A Dropbox account (may be a free one)
incron
daemon, to look for changes and sync, when changes occur
This post will only talk about the incron
slice of the cake, the Dropbox one is really ease, just get your free dropbox account.
incron
incron is according to its page:
This program is an "inotify cron" system. It consists of a daemon and a table manipulator. You can use it a similar way as the regular cron. The difference is that the inotify cron handles filesystem events rather than time periods.
As you can see, this is just the tool we need to accomplish this task.
Installation
Installation, should be very straight forward. Just use your Linux distribution package manager to install it. In my case using Arch Linux was:
pacman -S incron
The package came with a configuration example file: /etc/incron.conf.example
which listed some other configuration files.
/etc/incron.allow
: Here you configure the users allowed to use incron/etc/incron.deny
: Here you configure the users to deny the use incron/etc/incron.d
: This directory is examined by incrond for system table files.
Configuration
Basically, all you need to run incron
is:
- Create the file
/etc/incron.allow
(check inetc/incron.conf
if that is the right file to allow users), and add root and your user - Run:
incrontab -e
- Enter the folder to watch, the event to look for, and the command to run if the event happens.
The syntax of incrontab
is:
<folder> <mask> <command>
Where:
<folder>
is: The absolute path to the folder to watch
<mask>
is: A symbolic or numeric mask for events (see below)
<command>
is: The command to run on events.
Mask
- IN_ACCESS - File was accessed (read)
- IN_ATTRIB - Metadata changed (permissions, timestamps, extended attributes, etc.)
- IN_CLOSE_WRITE - File opened for writing was closed
- IN_CLOSE_NOWRITE - File not opened for writing was closed
- IN_CREATE - File/directory created in watched directory
- IN_DELETE - File/directory deleted from watched directory
- IN_DELETE_SELF - Watched file/directory was itself deleted
- IN_MODIFY - File was modified
- IN_MOVE_SELF - Watched file/directory was itself moved
- IN_MOVED_FROM - File moved out of watched directory
- IN_MOVED_TO - File moved into watched directory
- IN_OPEN - File was opened
The IN_ALL_EVENTS symbol is defined as a bit mask of all of the above events. Two additional convenience symbols are IN_MOVE, which is a combination of IN_MOVED_FROM and IN_MOVED_TO, and IN_CLOSE which combines IN_CLOSE_WRITE and IN_CLOSE_NOWRITE.
Solving Our Problem
Our real life example, was to be able to sync my jekyll blog with my dropbox folder when something change in my Jekyll folder.
Note: It is important to know that incron
is not recursive, so you need to manually add all sub-directories you want it to watch
I'm only going to look for changes in _posts
and images
folders. I'm going to add these lines in my user table:
incrontab -e
And will add these lines:
/path/to/my/jekyll/_post IN_CREATE,IN_DELETE,IN_CLOSE_WRITE rsync -av --delete --checksum /path/to/my/jekyll /home/my_user/Dropbox
/path/to/my/jekyll/images IN_CREATE,IN_DELETE,IN_CLOSE_WRITE rsync -av --delete --checksum /path/to/my/jekyll /home/my_user/Dropbox
Now I'm ready. Every time something change in those folders my server will sync my Jekyll folder with my Dropbox folder.