dirq.md

March 28, 2024 ยท View on GitHub

Motivation

The idea is to use a directory as a work queue with inotify as a subscription service to the queue. Any process with write perms can drop a file into a watched directory to trigger activity.

This can also be done with atomic rename, frequent stat(dir).st_mtime, readdir, but that is less efficient. It can happen that a program you do not control wants to just write & close, not rename into the directory. inotify lets you detect the union of both events simply for a more general facility.

As a very concrete example, you could direct your web browser to save new files to "$HOME/dl" and leave a dirq ~/dl got-dl instance running. The got-dl script/program can recognize various kinds of files and do appropriate stuff.

"Stuff" may be mv *.pdf files to "~/doc/" or starting a *.torrent download, making a simple browser click a gateway to auto-activity. You could rename a browser fetched file to take out spaces/other things that may need annoying shell quoting. You could (de)compress a file/otherwise re-encode it or even move it to another dirq-watched directory after processing. Queues have many uses. The only limit is your imagination. :)

There may be other interesting setups with other event classes.

Usage

  dirq [optional-params] [cmdPrefix: string...]

chdir(dir) & wait for events to occur on it.  For each delivered event, run
cmdPrefix NAME where NAME is the filename (NOT full path) delivered.

Handleable events are:
  access    attrib  modify   open   closeWrite closeNoWrite
  movedFrom movedTo moveSelf create delete     deleteSelf

Default events closeWrite (any writable fd-close) | movedTo (renamed into dir)
usually signal that NAME is ready as an input file.

dirq can monitor & dispatch for many dirs at once with repeated --dir=A cmdPfx
for A --dir=B cmdPfx for A patterns; events & wait are global.

Options:
  -e=, --events= set(Event) closeWrite,movedTo inotify event types to use
  -w, --wait     bool       false              wait4(kid) until re-launch
  -d=, --dir=    string     "."                directory to watch

History/Cultural

Circa 2006, Linux added a man 7 inotify system that obsoleted an inefficient & limited (must rename into) approach for this. So, I did a C program (had to use syscall(__NR_inotify_add_watch, ..) since it took glibc a while to wrap). dirq is a Nim port of this C program. (I pronounce dirq like "Dirk" myself, but you can do as you like.)

Future Work

I don't use BSD these days, but KQueue and similar facilities could allow this program to be a kind of portable command entry point for this limited subset of functionality. Maybe something like it already exists? I believe kqueue file monitoring pre-dates Linux inotify. Similarly, a few events like movedTo can be handled portably with a stat-loop, re-scanning directories upon mtime update.

inotifywait of inotify-tools does allow this, but a "command wrapper" use concept makes working with general filenames easier. Specifically, dirq simply populates the last argv[] slot with the filename received from the kernel & runs your program. This eliminates both quoting & parsing concerns. With inotifywait you would have to format things in a reliably parsable way which is yet another convention to fret about.

Bell Labs Plan 9 has a not dissimilar concept called "plumb"/"plumbers" but I believe these require a bit more cooperation.