DIREVENT(8)

πŸŽ€ DIREVENT(8) πŸŽ€ β€” Direvent User Reference, but make it a vibe

okay so bestie, you opened direvent(8) and now you're here, and honestly? you're in the right place. buckle up, this one's long but it's SO worth it. ✨


πŸ’… NAME πŸ’…

direvent β€” directory event monitor. that's it. that's the girl. she watches directories and she's fantastic at it. 🌸


πŸ¦‹ SYNOPSIS πŸ¦‹

direvent [-HVdfht] [-F NAME] [-P FILE] [-l PRIO] [-I DIR] [-T COMMAND]
[--debug] [--facility=NAME] [--foreground] [--include=DIR] [--lint]
[--pidfile=FILE] [--self-test=COMMAND] [--user=NAME] [CONFIG]

direvent -h
direvent --help

direvent -H
direvent --config-help

direvent --usage

direvent -V
direvent --version

like, there's the main girlboss invocation up top, and then a whole little fan club of "just tell me stuff and dip" forms. 🫢


🌈 DESCRIPTION 🌈

okay so real talk: GNU Direvent monitors a set of directories on the file system, and the second a file system event happens in any of them, she reacts. πŸ’… which directories, and which events? all specified in the configuration file, bestie. and when one of those events fires, she runs an external command that you set up for exactly that event. no cap.

here are the generic events she can watch for, and this is the whole list, don't skip:

  • create β€” a file was created. new baby alert. 🍼
  • delete β€” a file was deleted. gone, reduced to atoms. πŸ’€
  • write β€” a file was written to. someone's getting content.
  • change β€” a file was modified and closed. this one is supported on GNU/Linux, FreeBSD, and NetBSD. (sorry to the other platforms, it's giving limited edition. 😭)
  • attrib β€” file attributes have changed. this includes changes in the file ownership, mode, link count, etc. the glow-up is internal.

depending on the interface the underlying operating system hands over, direvent can also trace a bunch of system-dependent events, which can give you better resolution. those live in the SYSTEM DEPENDENCIES section down below, don't worry, we get there. ✨

now, a watcher? that's a configuration entity inside direvent that ties a set of directories to a set of events, and tells the program to run a specified external command whenever any of those events happen in any of those directories. that external command is called a handler, and it can pull info about the event that triggered it from environment variables, or from its command line. see HANDLER ENVIRONMENT below. iykyk. πŸ‘‘

watchers are declared in the configuration file direvent.conf, which lives in the system configuration directory β€” normally /etc. classic.

and if you want to be ✨different✨, you can use an alternative configuration file by passing its pathname as the command line argument (that's the CONFIG parameter in the SYNOPSIS above, bestie). main character energy.


✨ OPTIONS ✨

  • -d, --debug β€” crank up the debug verbosity level. more -d, more tea. 🍡
  • -F, --facility=FACILITY β€” log under this syslog facility. allowed values for FACILITY are a decimal number, or any of these symbolic names: auth, authpriv, cron, daemon, ftp, local0 through local7, lpr, mail, news, user, and uucp. and heads up: the option -F 0 directs logging to the standard error. πŸ“’
  • -f, --foreground β€” run in the foreground. no hiding in the background, she's standing right there.
  • -I, --include-directory=DIR β€” add DIR to the include search path. when she's looking for a file to be included in the #include (#include_once) statement, direvent scans first the directories given with -I options (in the same order as given on the command line), and then the directories in the standard include search path. that standard path is defined at compile time, and you can peek at it in the output of the --help option. πŸ‘€
  • -l PRIO β€” while connected to a terminal, direvent outputs its diagnostics messages to stderr and, if configured, to syslog. this option limits the amount of information output to the standard error. PRIO is one of the following priorities (in order of increasing severity): debug, info, notice, warning, err, crit, alert, emerg. when this option is given, only messages with a priority level equal to or greater than PRIO get duplicated on the standard error. so it's a whole vibe filter. πŸŽ€
  • -P, --pidfile=FILE β€” write the PID to FILE.
  • -T, --self-test=COMMAND β€” run in self-test mode. in this mode direvent starts the external command supplied as the argument to this option, and keeps running until that command exits. if the command terminates normally, direvent exits with the code returned by it. if the command terminates on SIGHUP, direvent exits with code 0. if it terminates on another signal, direvent exits with code 2. πŸ“Š COMMAND can include any command line options or arguments, as long as it's properly quoted. it is invoked as /bin/sh -c COMMAND in the environment of the parent direvent process. and the macro variable $self_test_pid holds the PID of the COMMAND (see the section VARIABLE EXPANSION in direvent.conf(5)).
  • -t, --lint β€” check the configuration file for errors and exit. a little wellness check. πŸ§–
  • -u, --user=USER β€” run as this USER.

informative options β€” these ones just cause the program to display the requested piece of information and exit. no strings attached, she's not staying:

  • -h, --help β€” output a terse help summary and exit.
  • -H, --config-help β€” describe configuration file syntax. the config lore drop. πŸ“–
  • --usage β€” show available command line options.
  • -V, --version β€” print program version and copyright information.

πŸ’œ CONFIGURATION πŸ’œ

the default configuration file is /etc/direvent.conf. if a file name is supplied as an argument to the program, that file gets read instead. periodt.

the full syntax tea is spilled in direvent.conf(5), so this section is just the short version. okay here we go:

three types of comments are allowed, and they are:

  • inline comments, which begin with a # or // and extend to the end of the line
  • multi-line comments, which comprise everything enclosed between /* and */

comments and empty lines are ignored. whitespace characters are ignored as well, except as they serve to separate tokens. so the whitespace is decorative, not load-bearing. πŸŽ€

a token is a string of consecutive characters from the following classes: alphanumeric characters, underscores, dots, asterisks, slashes, semicolons, commercial at's, and dashes. that's the whole VIP list.

any other sequence of characters has to be enclosed in double quotation marks in order to represent a single token. so if your thing isn't on the list, wrap it up. 🎁

configuration statements consist of a keyword and a value separated by any amount of whitespace, and the statement is terminated with a semicolon. a block statement is a collection of statements enclosed in curly braces. very demure.

the most important configuration statement is watcher. she's defined like this:

watcher {
    path PATHNAME [recursive [LEVEL]];
    event EVENT-LIST;
    command COMMAND-LINE;
    user NAME;
    timeout NUMBER;
    environ ENV-SPEC;
    option STRING-LIST;
}

each watcher statement tells direvent to monitor the events listed in EVENT-LIST that happen in the directories specified by PATHNAMEs in path statements β€” and yes, any number of path statements can be given. when any such event is detected, the COMMAND-LINE will be executed. πŸ’₯

each directory defined with the recursive keyword gets watched recursively. what does that mean, bestie? it means that for each subdirectory created inside it, direvent will install a watcher similar to that of its parent directory. the optional LEVEL can be used to set up a cut-off nesting level, beyond which the recursive operation is disabled. πŸ›‘

the PATHNAME is not required to be a directory β€” she can as well be a file of any type. and that file is not required to exist, either. if it doesn't exist, direvent will defer configuring the watcher until the file is eventually created. she plays the long game. ⏳

everything else is optional. the user statement can be used to execute the COMMAND-LINE as the user NAME β€” provided, of course, that direvent was started with root privileges. the timeout specifies the maximum amount of time (in seconds) the command is allowed to run, and it defaults to 5. the environ statement modifies the command environment (see the next section). finally, the option statement supplies additional options β€” you can use it, for example, to divert the command's output to syslog. πŸ™ˆ

the program's logging is controlled by the debug and syslog statements.

  • debug NUMBER; β€” sets the debugging level to NUMBER, which is an integer value between 0 and 4. zero is the default and it means debugging is disabled. the bigger the NUMBER, the more detailed the debugging information that gets output. πŸ”

the syslog statement controls the syslog logging:

syslog {
    facility STRING;
    tag STRING;
    print-priority BOOL;
}

the pidfile statement instructs the program to write its PID to the named file after disconnecting from the controlling terminal. πŸ“


🌸 HANDLER ENVIRONMENT 🌸

the handler that gets executed on an event is defined by the command statement in the watcher configuration block (peep direvent.conf(5) for that). before executing, the following operations are performed, in order, and we are NOT skipping any of them:

  1. the current working directory is set to the directory where the event occurred. πŸ“
  2. if the global environ statement is present, the current environment is modified according to its rules.
  3. if the environ statement is present in the watcher, the environment is further modified according to its rules. see the description of the environ statement in direvent.conf(5).
  4. the standard input is closed. if the stdout option is supplied, the standard output is captured and redirected to the syslog. otherwise it is closed. if the stderr option is supplied, the standard error is captured and redirected to the syslog. otherwise it is closed. all file descriptors above 2 are closed. yeah, ALL of them. πŸšͺ
  5. macro variables are expanded in the command line. unless the shell option is set, environment variables are expanded as well. see the section VARIABLE EXPANSION in direvent.conf(5). for example, if the handler is about to be executed for the write event on the file somefile, and the command definition was:
command "/libexec/handler -e '$genev_name' -f '$file'";

then the resulting command line will be:

/libexec/handler -e 'open' -f 'somefile'
  1. if the shell option is set, the handler is invoked via the shell, as $SHELL -c command. 🐚
  2. otherwise, word splitting is performed on the resulting command line. the first word is treated as the pathname of the program, which is then invoked via the execve system call.

🧚 SYSTEM DEPENDENCIES 🧚

Direvent relies on the event monitoring API provided by the kernel. that's the whole vibe. the kernel handles the watching, she handles the reacting. πŸ’«


✨ okay that's part 1 bestie, part 2 is right behind me, don't go anywhere ✨

✨ Linux ✨

On Linux, direvent vibes with inotify(7). That's the whole interface bestie, no cap. πŸ’…

Okay so here's the tea: the max number of watches a user process can have is controlled by the fs.inotify.max_user_watches system variable. Normally it's set to 8192, which is genuinely quite enough for most purposes, like don't even stress. But β€” and this is the important part β€” if you're monitoring a big number of directories and/or you're using recursive watchers, you may need more watches. In that case, use sysctl(8) to raise the limit, e.g.:

sysctl -w fs.inotify.max_user_watches=16384

Most GNU/Linux distributions provide the file /etc/sysctl.conf which can be used to set this variable on startup. iconic of them honestly.

The following system-dependent events are defined on systems that use inotify(7):

  • ACCESS β€” a file was accessed. πŸ‘€
  • ATTRIB β€” a file's metadata changed.
  • CLOSE_WRITE β€” a writable file was closed.
  • CLOSE_NOWRITE β€” an unwritable file closed.
  • CREATE β€” a file was created. ✨ new file just dropped
  • DELETE β€” a file was deleted. πŸ’€
  • MODIFY β€” a file was modified.
  • MOVED_FROM β€” a file was moved out from a monitored directory.
  • MOVED_TO β€” a file was moved into a monitored directory.
  • OPEN β€” a file was opened.

πŸ¦‹ BSD πŸ¦‹

When compiled on BSD systems (including Darwin), direvent uses kqueue(2). This interface needs an open file handle for each file in a monitored directory, which means that the number of watchers is limited by the maximum number of open files. Use ulimit -n NUM to raise it to a higher number. manifesting a higher number for u bestie 🫢

Since it operates on files, kqueue does not provide direct support for the create generic event. Direvent works over this disadvantage by keeping track of the contents of each monitored directory and rescanning it each time a WRITE system event is reported for it. It then generates the open event for each file that appeared after the last scan. Real talk: such a rescan can consume considerable time if a directory has a very large number of files in it. 😭 Not the slow rescan era.

Further, the change event is supported only on FreeBSD and NetBSD. periodt.

The following system-dependent events are available:

  • DELETE β€” the unlink() system call was called on the monitored file.
  • WRITE β€” a write occurred on the file.
  • EXTEND β€” the file was extended.
  • ATTRIB β€” the file attributes have changed.
  • LINK β€” the link count on the file changed.
  • RENAME β€” the file was renamed.
  • REVOKE β€” access to the file was revoked via revoke(2) or the underlying file system was unmounted.

Additionally, the following system events are supported by FreeBSD and NetBSD:

  • CLOSE β€” file opened read-only writing was closed.
  • CLOSE_WRITE β€” file opened for writing was closed.
  • OPEN β€” file was opened.
  • READ β€” file was read.

🌈 Darwin 🌈

Essentially the same as BSD, no biggie. The main difference compared to Linux and BSD is that on Darwin the watchers are set after disconnecting from the controlling terminal, because Darwin lacks the rfork(2) call and the event queue cannot be inherited by the child process. Darwin really said "I'll do it my way" and honestly? respect.


πŸ’– EXIT CODE πŸ’–

  • 0 β€” successful termination. we ate and left no crumbs. πŸ‘‘
  • 1 β€” command line usage error.
  • 2 β€” another error occurred.

πŸ”₯ SEE ALSO πŸ”₯


πŸ’… AUTHORS πŸ’…

Sergey Poznyakoff β€” the main character honestly.


πŸŽ€ BUG REPORTS πŸŽ€

Report bugs to <bug-direvent@gnu.org.ua>. Found a lil glitch? tell them, don't just suffer in silence bestie. 🫢


Copyright Β© 2012-2026 Sergey Poznyakoff

License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law. (that's the scary-but-true part, so like, know that going in 😭)


okay that's literally the whole page bestie, you're officially a direvent girlie now πŸ§šβ€β™€οΈπŸ’œ this was DIREVENT(8), dated June 5, 2026, and omg go touch some files, you've earned it. mwah πŸ’‹βœ¨

πŸ“¦ where this page comes from