Motivation
Sometimes, I want to implement tools which cover some of my usecases. Sometimes, these tools have been implemented already in a mature manner. entr is a tool few people know, but is fundamental to my work.
Idea
Let’s us consider a simple Makefile script. Let us store doc.tex
:
\documentclass{article}
\usepackage{fontspec}
\usepackage{geometry}
\geometry{a4paper}
\begin{document}
Hello World!
\end{document}
Furthermore, Makefile
:
all:
lualatex --interaction=nonstopmode doc.tex
Now, let us run entr
:
ls doc.tex | entr make
The result of this non-terminating command is that lualatex will be run (through Make) whenever doc.tex
changes. In this case, make
is called utility. Actually, you could also invoke (without Make
) …
ls doc.tex | entr -- lualatex --interaction=nonstopmode doc.tex
Fundamentals
-
entr
is the obvious usecase for the inotify API. inotifywait (via inotify-tools) is another tool. Originally, I wrote a python script implementing entr with the inotify package. -
Many servers in debug mode have interfaces which restart upon file changes. Older tools don’t.
entr
bridges the gap.
Examples (via documentation)
-
Rebuild a project if source files change, limiting output to the first 20 lines:
find src/ | entr -s 'make | sed 20q'
-
Launch and auto-reload a node.js server:
ls *.js | entr -r node app.js
-
Clear the screen and run a query after the SQL script is updated:
echo my.sql | entr -cp psql -f /_
-
Rebuild project if a source file is modified or added to the src/ directory:
while true; do ls src/*.rb | entr -d make; done
-
Self-terminate after a file is updated
ls * | entr -p 'kill $PPID'
Details
-
The list of files to watch must be provided as stdin input (e.g. via a pipe). I don’t know how it behaves for more complex usecases like newlines in the file’s basename.
find
can be a helpful utility to generate filenames of a tree. -
entr
will run the utility whenever space is pressed. q terminates entr. -
entr
will run once immediately when invoked.-p
disables this behavior. -
entr -c
runclear
before an update. -
entr -n
disables interactivity. -
Inotify does not support recursively watching directories, meaning that a separate inotify watch must be created for every subdirectory.
entr
supports this usecase, but I don’t know about limitations (like e.g. directory sizes).
systemd file to run sphinx whenever a source file changes
Just as an example: I use this systemd unit file to regenerate sphinx output whenever a source file changes:
[Unit]
Description = My Sphinx for personal notes
[Service]
User = meisterluk
Type = simple
PIDFile = /run/my-sphinx.pid
ExecStart = sh -c 'find /home/meisterluk/my-sphinx/source -type f | entr -d -n /home/meisterluk/infrastructure/venv-sphinx/bin/sphinx-build -b html /home/meisterluk/my-sphinx/source /home/meisterluk/my-sphinx/build/html'
StandardOutput = syslog+console
Restart = always
RestartSec = 1s
StartLimitInterval = 60
StartLimitBurst = 10
[Install]
WantedBy = multi-user.target
I don’t think this is the best configuration, but it works for my usecases. The sh
command utilizes the appropriate python virtual environment.