Eric Radman writes about Unix tools and BSD systems, and is the author of entr and pg_tmp.
Commenters repeatedly praise entr, which reruns commands when files change, for its solid design, cross-platform support, tmux fit, and good documentation.
Lots of ways! So this is one of those things that's subtly quite interesting -- Make will both take all variables from the environment, and make them Make variables. So this command:
$ USER=my_name make psql
The above example is the creation of a temporary ENV variable (assuming your shell supports this feature, it's equivalent to doing an export but only for that line), and the USER variable (accessed by using $(USER) or ${USER} in your makefile somewhere) will be automatically populated.
That is distinct from the following:
$ make psql USER=my_name
What you've done there is actually make-specific, you're giving make a Make variable, so Make will know about $(USER)/${USER}, and it will also show up, because Make exposes it's variables to shells (each line is it's own shell) that is run[0]. So this Makefile:
.PHONY: my-tgt
my-tgt:
echo -e "double dollar to print a bash var => $$MYVAR"
Produces the same thing -- $$MYVAR is actually a way to use a shell variable (the $ has to be escaped), but you get the same result putting USER= before and after:
$ MYVAR=from-the-shell make my-tgt
double dollar to print a bash var => [from-the-shell]
$ make my-tgt MYVAR=from-make
double dollar to print a bash var => [from-make]
All…
I recently wrote an autorunner[1] (like Entr[2] and Watchexec[3]) so I have some recent exposure to this problem. (I will be releasing it on Github shortly.) My autorunner allows running interactive programmes, so it is very sensitive to lingering child processes.
For the purposes of the autorunner, I use approach 1.1.3 (“always write down the pid of every process you start, or otherwise coordinate between A and B”) and leave it to the user to figure out what happens if the child process misbehaves with relation to any processes it starts.
However, I want to point out that approach 1.1.4 (“A should run B inside a container”) is easier to do than one might expect, and I'd like to plug one of my favourite utilities—Bubblewrap[4]. The Bubblewrap documentation says “[y]ou are unlikely to use it directly from the commandline, although that is possible” but I have built some amazing little tools from it.
Try the following invocation:
bwrap --ro-bind / / --proc /proc --unshare-pid ps
This launches `ps` in a PID namespace with a new `/proc` (since `ps` will read from the host proc otherwise) and the root filesystem mounted readonly. Any procesesses within the PID namespace should have been created by the immediate command that `bwrap` launched. There are also flags `--die-with-parent` and `--as-pid-1` which can further reduce runtime overhead. If you really need a supervisor process, this can be as simple as a `/bin/sh` script that `kill TERM --timeout 1000 KILL` in a loop…
Wow. I wasn't expecting anything like a filesystem monitor in git(1) itself.
They post says Jeff Hostetler, the author of the patches, will make a blog post delving into it. So it's worth bookmarking that post and swinging back. It's bound to be an interesting one!
Apparently git 2.16 had a fsmonitor hook for external filewatcher like watchman (it got passed me): https://github.com/git/git/commit/def4376711f607914bfb784f8de21867062fa284
This kind of change needs to be tailored to the platform, it says just Mac (FSEvents?) and Windows (ReadDirectoryChangesW?) for now. So can we expect Linux (inotify?) and BSD (kqueue*) in the future?
Anyway, I hope this venture is fruitful. The premise of having cross-platform file watching without needing an extra application is delightful.
Thank you Jeff!
* I believe one area that may be tricky is kqueue, I believe it has limits in watching directories, needing a file descriptor for each file.
P.S. I would like to drop a link to entr(1), a lightweight cross platform file watcher: https://eradman.com/entrproject/
The author describes the same TUI app workflow I've settled on. Three notes:
- entr is a good livereload tool: https://eradman.com/entrproject/. I prefer to wrap the livereload scripts in a Makefile, under something like `make dev`.
- Managing layout arithmetic by yourself is a real pain. A widget abstraction like Bubbletea's is very helpful. Also, don't forget about weird Unicode characters (eg. emoji) potentially breaking width calculations.
- Since this follows the Elm architecture, consider storing your data the Elm way into one big, flat Model. Elm webapps turn into headaches when you split state among submodels. I think the same happens in TUI apps. I'm glad the author found a solution with a tree of models and message passing. But personally, I'd rather have a Model with 100 fields than the complexity of sumbodels.
Garden[1] is a tool we built (yes, I'm affiliated :)) that has a lot of this functionality built-in. Might fit your use case.
We recently re-wrote the hot reload functionality to use Mutagen[2] under the hood and it's insanely fast (<200ms anecdotally). It also does two way sync which can be useful. The old implementation used rsync but a lot of our Windows users struggled with that. So I figured I'd share in case that sounds familiar.
What happens after a sync event depends on the stack, but we've had pretty good success with Entr[3]. We often have it watch a single file so that multiple watchers in a shared dev cluster don't eat up all the node's resources.
1: https://github.com/garden-io/garden
2: https://mutagen.io/
3: http://eradman.com/entrproject/
Looks interesting, I like that it's packaged as a single binary so it's easier to install. The idea to have default behaviors for different extension types is also cool. I've used entr[1] in the past--did you have a look at that tool? There seems to be some trickiness with things like "-r" to work properly in as many cases as possible. I also had an issue where it was hard to run entr in a Docker container on Mac due to some inotify issues or something. You may need to watch out for that!
Thanks for sharing :)
[1]: http://eradman.com/entrproject/