pages tagged system-callThe illusion of self consciencehttp://rafael.kontesti.me/blog/tags/system-call/The illusion of self conscienceikiwiki2012-09-22T14:46:07ZInotify for bash programmershttp://rafael.kontesti.me/blog/posts/Inotify_for_bash_programmers/2012-09-22T14:46:07Z2012-09-22T14:31:58Z
<h1>Inotify for bash programmers</h1>
<p>There are amazing system calls on a modern system
nowadays. Unfortunately, not all of them are exposed as a unix style
program. One such system call is inotify.</p>
<p>Have you ever needed to watch a file or a directory for changes? I have.
I've written software that needs to be called whenever there's new data
for processing in a directory. My usual approach to this is to add the
command in cron and keep on polling for new files. That works, but
wouldn't it be nicer if the system told us about changes, so we could
process the new file right away? Linux already has a mechanism for that
(I don't know if there's such a call in BSD world, I don't use them
anyway), it's the inotify system call.</p>
<p>I wrote code (I used C++ merely because I needed a map and
C is so bad with such data structure) which exposes inotify for scripts. It allows me to write a script to call a command
whenever a new file is created in /tmp. Here's how to do that using
awk:</p>
<pre><code>$ inotifier /tmp IN_CREATE | awk '{ system("cat "$3$4); }'
</code></pre>
<p>If I execute the command <strong>echo bla > /tmp/test</strong>, then the example
above will print <strong>bla</strong>.</p>
<p>inotifier allows me to watch all events as well. One can use it to
decide which event to filter and even to debug what a certain software
is doing.</p>
<pre><code>$ inotifier /tmp IN_ALL_EVENTS
IN_ISDIR,IN_OPEN 0 /tmp/
IN_CLOSE_NOWRITE,IN_ISDIR 0 /tmp/
IN_CREATE 0 /tmp/ test2
IN_OPEN 0 /tmp/ test2
IN_ATTRIB 0 /tmp/ test2
IN_CLOSE_WRITE 0 /tmp/ test2
</code></pre>
<p>That's the output after executing <strong>ls /tmp</strong> and <strong>touch /tmp/test2</strong>.</p>
<p>The output of inotifier comes from inotify(7) interface. inotify gives
me a <strong>inotify_event</strong> struct every time an event is fired. The tab
separated output of inotifier are the following struct members (in
order): <strong>mask</strong>, <strong>cookie</strong>, <strong>wd</strong>, and <strong>name</strong>.</p>
<p>While inotify gives me a bit mask, I transform it into a comma-separated
list of event names (<strong>IN_ISDIR,IN_OPEN</strong>). I do that because I believe
it's easier to work with bash that way (and it's easier on the eyes as
well).</p>
<p>When using inotifier, it's possible to watch for more than one event,
for example:</p>
<pre><code>$ inotifier /tmp IN_OPEN,IN_CREATE
</code></pre>
<p>watches for files created inside /tmp and for the open event in the
directory /tmp (usually used for listing its contents).</p>
<p>It's possible to watch a file instead of a directory:</p>
<pre><code>$ inotifier /tmp/foo IN_OPEN
</code></pre>
<p>watches /tmp/foo for open events. Whenever someone opens /tmp/foo,
inotifier will output.</p>
<p>We can als watch more than one file at time:</p>
<pre><code>$ inotifier /tmp/foo IN_ALL_EVENTS /tmp/test IN_ALL_EVENTS
</code></pre>
<p>notifies us about all events in files /tmp/foo and /tmp/test.</p>
<h1>Download</h1>
<p>I didn't bothered creating a repository for this one. You can download
the software here:
<a href="http://rafael.kontesti.me/software/inotifier-1.1.tar.gz">inotifier-1.1.tar.gz</a>.
Inside the package there's a README file explaining how to compile it
(there's a manual page as well, inotifier.1). All you got to do is
<strong>make</strong> inside the untared directory and you're good to go.</p>
<p>I'm using a permissive license for this one, as usual.</p>