File: source-script-in-modulefile.rst

package info (click to toggle)
modules 5.6.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 23,036 kB
  • sloc: exp: 79,659; sh: 6,142; tcl: 5,900; makefile: 1,492; ansic: 474; python: 265; csh: 202; perl: 47; ruby: 44; lisp: 13
file content (238 lines) | stat: -rw-r--r-- 9,031 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
.. _source-script-in-modulefile:

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 :subcmd:`sh-to-mod` and
a new modulefile command named :mfcmd:`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 (:mfcmd:`setenv`, :mfcmd:`prepend-path`,
:mfcmd:`set-alias`, :mfcmd:`set-function`, ...).

:subcmd:`sh-to-mod` outputs these resulting modulefile commands. This output
can be redirected into a file to create a modulefile. :mfcmd:`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+**

Basic 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:

.. literalinclude:: ../../example/source-script-in-modulefile/foo-1.2/foo-setup.sh
   :language: bash
   :caption: foo-setup.sh

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

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

.. parsed-literal::

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

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

.. parsed-literal::

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

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

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

.. literalinclude:: ../../example/source-script-in-modulefile/modulefiles/foo/1.2
   :language: Tcl
   :caption: modulefiles/foo/1.2

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

.. parsed-literal::

    :ps:`$` module show foo/1.2
    -------------------------------------------------------------------
    :sgrhi:`.../modulefiles/foo/1.2`:

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

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

.. parsed-literal::

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

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

.. parsed-literal::

    :ps:`$` module unload foo/1.2
    :ps:`$` alias foo
    bash: alias: foo: not found
    :ps:`$` 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.

Usage with shell-specific scripts
---------------------------------

When the initialization script provided by software only defines environment
variables, this script could be used to setup the user environment through the
use of ``source-sh`` in a modulefile whatever the shell ran by user, as the
``module`` command will accurately translate script changes into the language
of the running shell.

For instance the ``foo/1.2`` module, that uses the ``source-sh`` modulefile
command over the ``foo-setup.sh`` bash script, could also be used when running
the ``tcsh`` or ``fish`` shell:

.. parsed-literal::

    :ps:`$` echo $version
    tcsh 6.22.03 (Astron) 2020-11-18 (x86_64-unknown-linux) ...
    :ps:`$` module show foo/1.2
    -------------------------------------------------------------------
    :sgrhi:`.../modulefiles/foo/1.2`:

    :sgrcm:`prepend-path`    PATH example/source-script-in-modulefile/foo-1.2/bin
    :sgrcm:`set-alias`       foo {foobin -q -l}
    :sgrcm:`setenv`          FOOENV arg1
    -------------------------------------------------------------------
    :ps:`$` module load foo/1.2
    :ps:`$` foo
    foo, version 1.2

Software may sometimes provide a specific script for each shell they support
as they do not perform their initialization the same way on every shell. Quite
often a shell function is defined for *sh* shells whereas an alias is setup
for *csh* shells (as such shells do not support shell function).

Dummy software *bar* is used to demonstrate this situation. *bar* is installed
in version 2.1 in ``example/source-script-in-modulefile/bar-2.1`` directory
and it provides a ``bar-setup.sh`` and a ``bar-setup.csh`` scripts to activate
itself in user environment, depending on the shell kind used.

.. literalinclude:: ../../example/source-script-in-modulefile/bar-2.1/bar-setup.sh
   :language: bash
   :caption: bar-setup.sh

.. literalinclude:: ../../example/source-script-in-modulefile/bar-2.1/bar-setup.csh
   :language: csh
   :caption: bar-setup.csh

To accurately initialize environment for *bar* software, the ``bar`` module
needs to call the ``.sh`` script if user is currently running a shell from the
sh family, or to call the ``.csh`` script if user runs a csh-kind shell.

.. literalinclude:: ../../example/source-script-in-modulefile/modulefiles/bar/2.1
   :language: Tcl
   :caption: modulefiles/bar/2.1

This way the ``bar`` shell function is initialized when loading module from a user
environment running a *sh* shell:

.. parsed-literal::

    :ps:`$` echo $BASH_VERSION
    5.1.0(1)-release
    :ps:`$` module use example/source-script-in-modulefile/modulefiles
    :ps:`$` module show bar
    -------------------------------------------------------------------
    :sgrhi:`.../modulefiles/bar/2.1`:

    :sgrcm:`prepend-path`    PATH example/source-script-in-modulefile/bar-2.1/bin
    :sgrcm:`set-function`    bar {
        barbin -q -l}
    -------------------------------------------------------------------
    :ps:`$` module load bar
    :ps:`$` type bar
    bar is a function
    bar () 
    { 
        barbin -q -l
    }
    :ps:`$` bar
    bar, version 2.1

Whereas the ``bar`` shell alias is setup on *csh* shell environment:

.. parsed-literal::

    :ps:`$` echo $version
    tcsh 6.22.03 (Astron) 2020-11-18 (x86_64-unknown-linux) ...
    :ps:`$` module use example/source-script-in-modulefile/modulefiles
    :ps:`$` module show bar
    -------------------------------------------------------------------
    :sgrhi:`.../modulefiles/bar/2.1`:

    :sgrcm:`prepend-path`    PATH example/source-script-in-modulefile/bar-2.1/bin
    :sgrcm:`set-alias`       bar {barbin -q -l}
    -------------------------------------------------------------------
    :ps:`$` module load bar
    :ps:`$` alias bar
    barbin -q -l
    :ps:`$` bar
    bar, version 2.1

.. vim:set tabstop=2 shiftwidth=2 expandtab autoindent: