

Poor man's IFTTT in 3 lines of code - fdorfbauer
http://blog.lagentz.com/general/automate-your-shell-scripts-using-inotify-and-inotifywait/

======
lloeki
Regarding the watermark generation process, although the bash script works, I
immediately reach for my old friend (GNU) make(1) for that kind of task.
Here's the Makefile:

    
    
        all: watermark
        
        done:=$(wildcard *-BD.pdf)
        src:=$(filter-out $(done),$(wildcard *.pdf))
        marked:=$(patsubst %.pdf,%-BD.pdf,$(src))
        
        watermark: $(marked)
        
        %-BD.pdf: %.pdf
        	./watermark_script.sh $< $@
    

The _done_ + _filter-out_ mumbo jumbo is there just because without it,
-BD.pdf would be matched by .pdf, and therefore would generate -BD-BD.pdf...
and so on (this is a loophole that the original bash script has, if parallel
runs are timed correctly). Putting the output files in another directory is
left ans an exercise for the reader.

The inotify script becomes:

    
    
        inotifywait -e create /home/user/pdfs && make -C /home/user/pdfs
    

There is another loophole here, in that the -BD.pdf are created in that
directory, so the script gets run again. It doesn't matter for our makefile,
which will do nothing on the second run, but there is the 'parallel runs if
timed correctly' issue of the original bash script.

Generally, GNU make has a bunch of very interesting facilities, making it
much, much more powerful than its ancestors (BTW, people interested may want
to take a look at an implementation of non-recursive make[0], which — while
being awesome — also shows up some useful make tricks).

Now, regarding the filesystem events and userland tools (which are awesome), I
wish there was a unified front-end for this kind of things (inotify on Linux,
fsevents on OSX...)

PS: I wish the comment form supported something like markdown, so that I could
escape those wildcards, and more.

[0] [http://stackoverflow.com/questions/559216/what-is-your-
exper...](http://stackoverflow.com/questions/559216/what-is-your-experience-
with-non-recursive-make)

~~~
rb2k_
I'm sorry if I missed this, but why would you use make instead of bash?

~~~
lloeki

        make figures out which files need updating
        make allows to write pattern rules (.c.o:, or %.o: %.c)
        you don't need to move files out of the 'inbox'
          to ignore them
        regenerating a file is a touch(1) away
        make is descriptive, not imperative (invaluable
          readability when you're coming back on it years later)
        should you ever need a second transformative step or
          a new dependency, it's trivial to insert, and make
          will figure stuff out
        make can trash intermediate results automatically
        make is crazy fast
        make variables are not environment variables
        make has multiple variable assignations, resulting in
          some early/late evaluation system (early with :=,
          late with =, $() is always late unless part of a :=)
        make outputs commands as they're executed (not with a global)
        make outputs nothing when commands are prefixed with @ (not with a global)
        make interrupts itself on a chain failure
        each make recipe line is executed in a distinct shell
    

You can set bash to do some of those things, or you can write bash code that
do some of those, but most of the time you end up just coercing bash into
behaving like make.

Of course I would not write everything in make. But knowing what make can do
makes it the obvious choice for some tasks, and helps you coming up with a
robust task/generator system in a snap, whereas coming up with a
task/generator system in bash quickly is already not _that_ easy, and making
it robust even less.

~~~
stonefroot
"make is crazy fast"

Make calls the shell in order to run programs, correct?

(IOW, does make call execve directly, as the shell does?)

~~~
lloeki
Indeed, execve in exec_command (job.c). That does not make it slow, since it's
the very last part of the game, and one you could not really do without.

------
chrisacky
I use this to compile my LESS scripts already. I was always getting really
frustrated with the options with LESS... either compile in the browser, or
compile manually. Both were actually a bit of a pain, (caching being the
biggest annoyance for browser compilation).

So I used inotifywait...

It would check for any modifications to my "CSS" folders recursively, and it
would then run my custom less compilation script [1] ...

    
    
         #!/bin/bash
         while inotifywait -e modify -r /var/www/site/public/static/css/base; do
           cd /var/www/site/public/static/css; node compile;
         done
    

(I also hooked this up to Fab [2], and used a "start"/"stop" script [3] to
pause the watch, so that I could manually control when inotify wait would be
watching.

[1] <https://gist.github.com/3497304> (My Custom LESS compile Script)

[2] <http://docs.fabfile.org/en/1.4.3/index.html> ( Fabric Command Line Tool )

[3] <https://gist.github.com/3497308> (Sample Fab Command )

If it would benefit anyone to know in greater details, I'd be happy to write a
blog post about automating compilation using these tools.

~~~
nosecreek
I solved this problem using <http://leafo.net/lessphp/>. Obviously that only
works if you are programming in PHP, but I would imagine there are similar
solutions available for other languages?

------
jawr
I found this a very intrusive site - I really dislike these animated slide in
fade in distractions.

~~~
haldean
Not only the slide-in nonsense, but also the wiggling "Try Me!" arrow on the
right. "You may also like" panels are becoming the Clippy of blogs and news
sites.

~~~
pbhjpbhj
Didn't see any of it with noscript on.

What's the "try me" pointing to? I tried clicking it and it did nothing,
scrolling down it just points to blank right margin all the way ...?

I have no problem with "you may also like" and have found the links useful on
occassion; anything animated without user interaction however is generally a
turn off for me.

~~~
icebraining
_What's the "try me" pointing to?_

Some kind of feedback tool about the site.

~~~
dice
I used the feedback tool to inform the author that the "Try me!" was annoying
enough to cause me to want to leave a nasty note.

So I guess it worked?

------
ambrop7
The inotify script likely has a race condition; if the directory is modified
while an update is running, it won't pick up the second modification, and will
wait in a dirty state until it is modified again. If anyone wants a race-free
solution, you should check out my NCD scripting language [1] which has an
integrated command to receive directory change notifications (last example in
Blockers section is a race-free solution to this problem).

[1] <http://code.google.com/p/badvpn/wiki/NCD>

~~~
nitrogen
After a very brief look, NCD looks very cool. I'm curious about the first
complete example. Is it possible to implement a delay of a few seconds before
the IP address is reset when the link is lost?

~~~
ambrop7
I've never seen why that would be useful. Switches and Ethernet cards aren't
that unreliable in my experience, and I've plugged cables into a different
switch in less than a few seconds :) I think if you _really_ needed that, the
nicest way would be to add it as a feature to net.backend.waitlink(). See
source [1] of this command, and source of sleep() [2] to see how to use a
timer. It may also be possible to hack it up without C-coding using blocker(),
spawn(), sleep() and maybe other control commands.

[1]
[http://code.google.com/p/badvpn/source/browse/trunk/ncd/modu...](http://code.google.com/p/badvpn/source/browse/trunk/ncd/modules/net_backend_waitlink.c)
[2]
[http://code.google.com/p/badvpn/source/browse/trunk/ncd/modu...](http://code.google.com/p/badvpn/source/browse/trunk/ncd/modules/sleep.c)

~~~
nitrogen
I've had a situation where an Ethernet connection would occasionally drop link
for a very small fraction of a second, which unnecessarily shut down the
interface and reset all TCP connections. Maybe a few second delay is too long,
but 500ms seems reasonable. Also, maybe I wouldn't want to keep the old
address blindly, but trigger a DCHP request if the link is dropped and
restored before the timeout.

Also, thanks for the pointers into the source code. It looks like I would want
to make the change around line 67 of net_backend_waitlink.c. I highly doubt
I'll actually get around to doing it though :).

~~~
ambrop7
So you really need this, would that mean you may be able to use my language
for something? If so, just say, and I can add this little feature, but I
wouldn't like spending time for nothing :)

~~~
nitrogen
I haven't seen this problem recently, so don't worry about it. I appreciate
the offer, though. Maybe some day I'll look into adding the feature for my
embedded Linux systems, if I ever add Ethernet disconnection detection.

------
m4re
In 2006, as inotify first hit the kernel, some friends and I wrote fsniper [1]
to accomplish this same task. There's also incron [2] which is similar. In
today's parlance we'd call fsniper "opinionated" about its workflow.

[1] <http://github.com/l3ib/fsniper> [2] <http://inotify.aiken.cz/>

------
danielweber
Someone please tell me what IFTTT is.

~~~
berberich
<http://ifttt.com/wtf>

------
gvsyn
Granted another linux specific method but I'd recommend incrond. Works very
well for such tasks. [http://www.cyberciti.biz/faq/linux-inotify-examples-to-
repli...](http://www.cyberciti.biz/faq/linux-inotify-examples-to-replicate-
directories/)

------
swah
I wrote something similar the other day, but failed to realize that having a
utility that locks until there are changes (vs one that calls a program when
changes happen) is much easier to integrate with bash scripts.

------
tosh
Great use-case for lnotify, haven't thought about that. Feels much cleaner
than having cron jobs for conversions like these.

~~~
oker1
With the listen gem you can write crossplatform scripts
(<http://rubygems.org/gems/listen>).

~~~
prakashk
For those of Perl persuasion, there are:

    
    
        * File::ChangeNotify (https://www.metacpan.org/module/File::ChangeNotify)
        * Filesys::Notify::Simple (https://www.metacpan.org/module/Filesys::Notify::Simple)

------
bergie
I've had some IFTTT-esque ideas with <http://noflojs.org/> as well

------
jcbmllgn
Is usersnap.com really facilitating better feedback or is it just annoying
people that visit your website?

~~~
fdorfbauer
Used as a feedback tool you are way faster to understand what your visitors
mean. Used as a bug reporting tool it's unbeatable: you get exactly what your
testers / users see in their browser. Please note that the Try-Me arrow is not
part of usersnap - that's maybe the annoying part you are referring to?

