There is a new version of this tutorial available for Debian 9 (Stretch).

Triggering Commands On File/Directory Changes With Incron on Debian Etch

This tutorial exists for these OS versions

On this page

  1. 1 Installing Incron
  2. 2 Using Incron
  3. 3 Links

This guide shows how you can install and use incron on a Debian Etch system. Incron is similar to cron, but instead of running commands based on time, it can trigger commands when file or directory events occur (e.g. a file modification, changes of permissions, etc.).

This document comes without warranty of any kind! I do not issue any guarantee that this will work for you!


1 Installing Incron

Incron is available in the etch-backports repository, so we have to add the following line to /etc/apt/sources.list:

vi /etc/apt/sources.list
deb etch-backports main contrib non-free

Let's import the archive key into apt...

wget -O - | apt-key add -

... and run

apt-get update

The etch-backports repository is inactive by default, so to install incron from it, we must use the following command:

apt-get -t etch-backports install incron


2 Using Incron

Incron usage is very much like cron usage. You have the incrontab command that let's you list (-l), edit (-e), and remove (-r) incrontab entries. To learn more about it, see

man incrontab

There you also find the following section:

If /etc/incron.allow exists only users listed here may use incron. Otherwise if /etc/incron.deny exists only users NOT listed here may use incron. If none of these files exists everyone is allowed to use incron. (Important note: This behavior is insecure and will be probably changed to be compatible with the style used by ISC Cron.) Location of these files can be changed in the configuration.

This means if we want to use incrontab as root, we must either delete /etc/incron.allow (which is unsafe because then every system user can use incrontab)...

rm -f /etc/incron.allow

... or add root to that file (recommended):

vi /etc/incron.allow

Before you do this, you will get error messages like this one when trying to use incrontab:

server1:~# incrontab -l
user 'root' is not allowed to use incron

Afterwards it works:

server1:~# incrontab -l
no table for root

We can use

incrontab -e

to create incron jobs. Before we do this, we take a look at

man 5 incrontab

because it explains the format of the crontabs. Basically the format is as follows...

<path> <mask> <command>

...where <path> can be a directory (meaning the directory and/or the files directly in that directory (not files in subdirectories of that directory!) are watched) or a file.

<mask> can be one of the following:

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 (*)

When monitoring a directory, the events marked with an asterisk (*) above can occur for files in the directory, in which case the name field in the
returned event data identifies the name of the file within the directory.

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.

The following further symbols can be specified in the mask:

IN_DONT_FOLLOW      Don't dereference pathname if it is a symbolic link
IN_ONESHOT          Monitor pathname for only one event
IN_ONLYDIR          Only watch pathname if it is a directory

Additionaly, there is a symbol which doesn't appear in the inotify symbol set. It is IN_NO_LOOP. This symbol disables monitoring events until the current one is completely handled (until its child process exits).

<command> is the command that should be run when the event occurs. The following wildards may be used inside the command specification:

$$   dollar sign
[email protected]   watched filesystem path (see above)
$#   event-related file name
$%   event flags (textually)
$&   event flags (numerically)

If you watch a directory, then [email protected] holds the directory path and $# the file that triggered the event. If you watch a file, then [email protected] holds the complete path to the file and $# is empty.

If you need the wildcards but are not sure what they translate to, you can create an incron job like this:

/tmp/ IN_MODIFY echo "$$ [email protected] $# $% $&"

Then you create or modify a file in the /tmp directory and take a look at /var/log/syslog - this log shows when an incron job was triggered, if it succeeded or if there were errors, and what the actual command was that it executed (i.e., the wildcards are replaced with their real values).

tail /var/log/syslog
Aug 21 17:26:50 server1 incrond[7111]: (root) CMD (echo "$ /tmp huhu IN_CREATE 256")

In this example I've created the file /tmp/huhu; as you see [email protected] translates to /tmp, $# to huhu, $% to IN_CREATE, and $& to 256.

Now enough theory. Let's create our first incron jobs. I'd like to monitor the file /etc/apache2/apache2.conf and the directory /etc/apache2/vhosts/, and whenever there are changes, I want incron to restart Apache. This is how we do it:

incrontab -e
/etc/apache2/apache2.conf IN_MODIFY /etc/init.d/apache2 restart
/etc/apache2/vhosts/ IN_MODIFY /etc/init.d/apache2 restart

That's it. For test purposes you can modify your Apache configuration and take a look at /var/log/syslog, and you should see that incron restarts Apache.

To list all defined incron jobs, you can run

incrontab -l
server1:~# incrontab -l
/etc/apache2/apache2.conf IN_MODIFY /etc/init.d/apache2 restart
/etc/apache2/vhosts/ IN_MODIFY /etc/init.d/apache2 restart

To delete all incron jobs of the current user, run

incrontab -r
server1:~# incrontab -r
removing table for user 'root'
table for user 'root' successfully removed


Share this page:

Suggested articles

10 Comment(s)

Add comment


By: A_Biondi

You've forgotten to say that the kernel must be with inotify compiled in, oterwise incron won't work...

By: UngaMan


 If you want to process some a file recently created, be careful in testing the IN_CREATE and IN_CLOSE_WRITE events after making it live.

It seems that IN_CREATE reacts when the file descriptor is created and not necessarily when the file has been fully filled.

I tried to make an automated copy of some long files created by a third-party software. It happened that the 3rd party-software created the descriptor but took its time to write the content from the buffer to the file. So incrond reacted to the newly created filename and performed the operation commanded by my script but the files were empty (288 bytes). After having realized that, I changed the IN_CREATE for IN_CLOSE_WRITE in order to give the right time. Now my script works nice.

 Great article you have here and thanks for posting it!

By: ~A!

Wanted to stop in and say thanks. This comment saved me a lot of heartache.

By: Anonymous

Thank you!! This was very helpful. Saved me a lot of time and frustration.

By: etkopa

Indeed, most of the time you want to use IN_CLOSE_WRITE. But be careful - some programs might close the file, and yet re-open it for more writing. There is not easy way to determine when the file has been written in full in some cases. A little sleep might help here as well, bit this is only w workaround really.

By: Chasalin

Yes, it is obvious

Yes, it's so obvious you might forget it.

In the demo, the /tmp/ dir is watched and changes are echoed.

Don't make the mistake I made to pipe that echo to the mail command.

It will make temp files and loop ;)

By: Stav61

We have some rather large files being dropped in to an ftp. We would like some scripts to initiate work on the files once the files are done uploading not when they are created. In addition there is more than one file going up. Any one have any ideas?  we would like the simplest solution considering the Perl scripts enacting on the files are pretty robust. We could edit the script files and iterate through the watched folder every time a file goes up to make sure the file count is right however that can fluctuate. Any help would be greatly appreciated.


By: Stavros Aloizos

You can variabilize the file name and port it to where ever you would like to send it or run whatever command you would like.

 /directory/being/watched IN_CLOSE_WRITE,IN_NO_LOOP  mv [email protected]/$# /directory/for/working/$#

This would be initiated at the end of the completion of uploading of a particular file (name) to a particular folder. What’s good about this method is that individual file is grabbed when it finishes and worked on. Without it affecting the other contents of the directory and other files being transferred.


By: Annon

I can't believe it's taken so long to come across this comment! Thank you

By: janl


with IN_CREATE I get for $# not the filename.jpg but filename.jpg.part

Tried it withIN_ALL_EVENTS and got filename.jpg.part in almost all instances.

It works with IN_MOVED_T.

Is there a setting/parameter that prevents $# to give back the name of the temporary filename.jpg.part ?