Environment Modules
One of the forgotten tools
Environment Modules is one of those open source projects that I wish more people would know and use. I always wonder why tools like asdf don’t provide support for it instead of rolling their own implementation. So lets increase awareness.
The Environment Modules package provides for the dynamic modification of a user’s environment via modulefiles.
So what does it do? Here is a small example:
~ $ type ansible
bash: type: ansible: not found
~ $ module avail -l ansible/
- Package/Alias -----------------------.- Versions --------.- Last mod. -------
/home/mjansen/local/etc/modules:
ansible/2.8.15 2.8 2020/10/28 18:43:05
ansible/2.9.13 2.9 2020/10/28 18:43:15
ansible/2.10.1 2.10:default 2020/10/28 18:42:56
~ $ module load ansible/2.9.13
~ $ ansible --version
ansible 2.9.13
config file = None
configured module search path = ['/home/mjansen/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/mjansen/local/opt/ansible/2.9.13/lib64/python3.8/site-packages/ansible
executable location = /home/mjansen/local/opt/ansible/2.9.13/bin/ansible
python version = 3.8.6 (default, Nov 09 2020, 12:09:06) [GCC]
~ $ type ansible
ansible is hashed (/home/mjansen/local/opt/ansible/2.9.13/bin/ansible)
~ $ module unload ansible
~ $ type ansible
bash: type: ansible: not found
So in short environment modules allow you to alter your shell session dynamically by
- Altering the content of environment variables
- Setting/Removing aliases
- Create functions in the users environment
- There is more in the modulefile man page.
Modulefiles are actually tcl scripts. It is a slightly weird (imo) looking scripting language. Tcl and environment modules are available forever. They are from the 1990s.
The ansible script above looks like this:
#%Module1.0#####################################################################
##
## ANSIBLE VERSION
##
proc ModulesHelp { } {
global version
puts stderr "\tActivates ansible v$version [ARA]"
}
set home $::env(HOME)
set version 2.9.13
set root $home/local/opt/ansible/$version
set ansible_callback_plugins [exec $root/bin/python3 -m ara.setup.callback_plugins]
module-whatis "Ansible V$version"
conflict ansible
append-path PATH $root/bin
setenv ANSIBLE_CALLBACK_PLUGINS $ansible_callback_plugins
So why should you care. As a hypothetical developer you probably need to install different versions of libraries and tools to check your programs against or with. Like different Qt Versions or compiler. Most developer I know then proceed to use shell scripts they source to deal with that. This does not allow easy unloading and switching. Utilizing environment modules gives you a much more pleasant experience. My list currently looks like this:
- Package/Alias -----------------------.- Versions --------.- Last mod. -------
/home/mjansen/local/etc/modules:
ansible/2.8.15 2.8 2020/10/28 18:43:05
ansible/2.9.13 2.9 2020/10/28 18:43:15
ansible/2.10.1 2.10:default 2020/10/28 18:42:56
catt 2019/08/26 14:58:23
editor/vim 2020/10/26 19:39:10
elixir_escripts 2020/11/11 05:29:32
elm/0.19.1-3 0.19:0.19.1:default 2020/03/31 22:24:21
go/1.13.6 2020/01/21 16:06:16
gopath 2020/01/21 16:16:09
groovy/2.4.7 2019/08/26 14:58:23
groovy/2.5.7 2019/08/26 14:58:23
home_install 2020/02/23 16:20:05
hugo/0.76.5 2020/10/28 18:46:11
hugo/0.80.0 2021/01/09 21:07:52
java/jdk1.8.0_172 2019/08/26 14:58:23
jupyter 2019/08/26 14:58:23
maven/3.3.9 2019/08/26 14:58:23
minishift 2020/03/29 16:29:17
novisual 2019/08/26 14:58:23
reclass/1.4.1 2020/01/27 14:27:20
reclass/git 2020/12/20 19:51:34
usr_local 2020/01/29 13:36:42
vit 2020/01/15 17:01:25
zeppelin/0.9.0-preview2 2020/10/29 16:42:13
Environment modules also has the concept of sessions which allows you to save and load different configurations. Either in
a central location (eg. ~/.module
) or to a file specified on the command line.
~ $ module save homepage
~ $ module savelist
Named collection list:
1) homepage
~ $ module saveshow homepage
-------------------------------------------------------------------
/home/mjansen/.module/homepage:
module use --append /home/mjansen/local/etc/modules
module load editor
module load gopath
module load go
module load hugo
-------------------------------------------------------------------
Modulefiles can even specify conflicts, so you don’t load two different versions of a library or program. They can also specify requirements, so you don’t forget to load a python version before loading ansible.
If you want to try environment modules one word of warning. In opensuse after installing environment modules it is not active. I guess the same applies to other distros. Shell initialization files for additional packages are a sore spot in most distros. You have to activate it manually in your shell initialization file (eg. bashrc).
# ACTIVATE ENVIRONMENT MODULES # {{{2
###############################################################################
case "$0" in
-sh|sh|*/sh) modules_shell=sh ;;
-ksh|ksh|*/ksh) modules_shell=ksh ;;
-zsh|zsh|*/zsh) modules_shell=zsh ;;
-bash|bash|*/bash) modules_shell=bash ;;
esac
source /usr/share/Modules/init/$modules_shell
test -r /usr/share/Modules/init/{$modules_shell}_completion && source /usr/share/Modules/init/{$modules_shell}_completion