Use incron to Trigger Action when File Changes

Written by
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:

  1. Create the file /etc/incron.allow (check in etc/incron.conf if that is the right file to allow users), and add root and your user
  2. Run: incrontab -e
  3. 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.