Source shell script in modulefile

When working with large software suite providing a shell script for their enablement in user environment, it is usually desired to also provide access to these software through module. However these software enablement may be complex and it may be wise to keep using the shell script provided by software editor rather crafting a modulefile from scratch.

This recipe describes how to make modulefiles for such software by using the enablement shell script provided with them.

Implementation

Modules version 4.6 introduces a new sub-command named sh-to-mod and a new modulefile command named source-sh. The sh-to-mod outputs as a modulefile content the environment changes done by the evaluation of a shell script passed as argument. On the other hand, the source-sh modulefile command sources environment changes done by the evaluation of a shell script passed as argument.

Both new features relies on the same mechanism that starts a designated shell to:

  • get current environment state (environment variables, shell aliases, shell functions and current working directory)
  • source designated shell script with defined arguments
  • get resulting environment state

Once done, environment prior and after script source are compared to determine the corresponding environment changes and translate those changes into modulefile commands (setenv, prepend-path, set-alias, set-function, ...).

sh-to-mod outputs these resulting modulefile commands. This output can be redirected into a file to create a modulefile. source-sh on the other hand sources the resulting modulefile commands to evaluate them as if they were written in the modulefile calling source-sh.

sh-to-mod and source-sh support the following shells: sh, dash, csh, tcsh, bash, ksh, ksh93, zsh and fish.

Compatible with Modules v4.6+

Usage example

For this recipe, a dummy software named foo is used as example. foo is installed in version 1.2 in example/source-script-in-modulefile/foo-1.2 directory and it provides a foo-setup.sh script to activate itself in user environment:

foo-setup.sh
#!/bin/bash
export FOOENV="$1"
export PATH=$(dirname $BASH_SOURCE)/bin:$PATH                                                             
alias foo='foobin -q -l'

First line of foo-setup.sh script helps to identify which shell needs to be used to evaluate it: bash.

sh-to-mod may be used to get this script translated as a modulefile:

$ module sh-to-mod bash example/source-script-in-modulefile/foo-1.2/foo-setup.sh arg1
#%Module
prepend-path    PATH example/source-script-in-modulefile/foo-1.2/bin
set-alias       foo {foobin -q -l}
setenv          FOOENV arg1

Output could be redirected into a foo/1.2 file and make it the modulefile to enable software foo:

$ mkdir -p modulefiles/foo
$ module sh-to-mod bash example/source-script-in-modulefile/foo-1.2/foo-setup.sh arg1 >modulefiles/foo/1.2
$ module use ./modulefiles
$ module show foo
-------------------------------------------------------------------
modulefiles/foo/1.2:

prepend-path    PATH example/source-script-in-modulefile/foo-1.2/bin
set-alias       foo {foobin -q -l}
setenv          FOOENV arg1
-------------------------------------------------------------------

Instead of transforming shell script in modulefile, a modulefile using source-sh modulefile command to evaluate shell script at modulefile evaluation time may be written:

$ cat <<EOF >modulefiles/foo/1.2
#%Module4.6
source-sh bash example/source-script-in-modulefile/foo-1.2/foo-setup.sh arg1
EOF

When displaying a modulefile using source-sh modulefile command, modulefile commands resulting from source-sh evaluation are reported:

$ module show foo/1.2
-------------------------------------------------------------------
modulefiles/foo/1.2:

prepend-path    PATH example/source-script-in-modulefile/foo-1.2/bin
set-alias       foo {foobin -q -l}
setenv          FOOENV arg1
-------------------------------------------------------------------

Loading this foo/1.2 module will enable access to software foo:

$ module load foo/1.2
$ alias foo
alias foo='foobin -q -l'
$ foo
foo, version 1.2

Unloading foo/1.2 module will properly revert these environment settings:

$ module unload foo/1.2
$ alias foo
bash: alias: foo: not found
$ foobin
bash: foobin: command not found

As conclusion, these new features enable to leverage the setup scripts that are provided along with software to make them reachable from the module environment.