Monday, March 15, 2021

Linux Environment Management: direnv does it all

 

Linux Environment Management: direnv does it all

A few years back I wrote about different options for linux environment management.  I recently learned about another option, direnv.  I think I'm convinced that it is the only tool you need.  Read this as if it's another section added to that previous post.

Use direnv

Straight from the direnv website: "direnv is an extension for your shell. It augments existing shells with a new feature that can load and unload environment variables depending on the current directory.  Before each prompt, direnv checks for the existence of a .envrc file in the current and parent directories. If the file exists (and is authorized), it is loaded"

This happens automatically, so it solves the problem of the "Explicit Environment Files" solution above in a way that is much more convenient than the "Per-command Environment Files" solution. The .envrc files are in standard shell syntax and it properly unloads environments like the "Smart Environment Manager Tool" mentioned above as well.  It has the downside that it is not easy to share the same environment setup in multiple directories.

I'm not sure if there is a simple solution that gives us both of those things, but we have the option with direnv to choose any of the three the discussed environment setup solutions in any given terminal.

Why not all three?

direnv is powerful enough to allow all three techniques for shell configuration described above.

Standard direnv

The default automatic direnv behavior is enabled by putting this in your .bashrc file:

eval "$(direnv hook bash)"

If you want to easily choose between standard direnv and the below option when you start a new shell you could encapsulate this in a shell function named direnvenable.  When your terminal starts up, you would run that function if you want standard direnv behavior.

The equivalent of Shell Initialization Files

To "source" a given .envrc file you can just spawn a subshell using the direnv exec command, passing it the path to a project and its .envrc file:

direnv exec $(readlink -f /path/to/git/clone) $SHELL -i

I would suggest wrapping this a shell function to make it easier.

The equivalent of Per-command Environment Files

This can work in conjunction with the automatic direnv behavior (you can run direnvenable and still use this for commands outside of any project directory).  This is a good way to run commands in scripts using the correct shell environment.  It's the same direnv exec call above prefixing any shell command:

direnv exec $(readlink -f /path/to/git/clone) <command>

I would also suggest wrapping this in a shell function to make it easier.


Conclusion

direnv gives you the power of never needing to manually source an environment setup script when you are working in a git clone of a project. It also gives you the ability to use project settings from a git clone in other directories if needed.