MODULEFILE(5)
๐ MODULEFILE(5) ๐
bestie, welcome to the Modules manual โ this page is all about modulefile, the files containing Tcl code for the Modules package. buckle up, itโs giving vintage Unix but make it cute โจ
๐ NAME ๐
modulefile โ files containing Tcl code for the Modules package.
๐ธ DESCRIPTION ๐ธ
okay so modulefiles are written in the Tool Command Language, Tcl(n), and they get interpreted by the modulecmd.tcl program via the module user interface. They can be loaded, unloaded, or switched on-the-fly while the user is working; and they can be used to implement site policies regarding the access and use of applications. ๐
A modulefile begins with the #%Module file signature, also called the Modules magic cookie. A version number may be placed after this string. The version number is useful as the modulefile format may change thus it reflects the minimum version of modulecmd.tcl required to interpret the modulefile. If a version number doesn't exist, then modulecmd.tcl will assume the modulefile is compatible. Files without the magic cookie or with a version number greater than the current version of modulecmd.tcl will not be interpreted. If the mcookie_version_check configuration is disabled the version number set is not checked. ๐
Each modulefile contains the changes to a user's environment needed to access an application. Tcl is a simple programming language which permits modulefiles to be arbitrarily complex, depending upon the application's and the modulefile writer's needs. If support for extended tcl (tclX) has been configured for your installation of the Modules package, you may use all the extended commands provided by tclX, too. ๐ฆ
A typical modulefile is a simple bit of code that set or add entries to the PATH, MANPATH, or other environment variables. A Modulefile is evaluated against current modulecmd.tcl's mode which leads to specific evaluation results. For instance if the modulefile sets a value to an environment variable, this variable is set when modulefile is loaded and unset when modulefile is unloaded. ๐
Tcl has conditional statements that are evaluated when the modulefile is interpreted. This is very effective for managing path or environment changes due to different OS releases or architectures. The user environment information is encapsulated into a single modulefile kept in a central location. The same modulefile is used by every user on any machine. So, from the user's perspective, starting an application is exactly the same irrespective of the machine or platform they are on. ๐
modulefiles also hide the notion of different types of shells. From the user's perspective, changing the environment for one shell looks exactly the same as changing the environment for another shell. This is useful for new or novice users and eliminates the need for statements such as "if you're using the C Shell do this ..., otherwise if you're using the Bourne shell do this ...". Announcing and accessing new software is uniform and independent of the user's shell. From the modulefile writer's perspective, this means one set of information will take care of every type of shell. ๐
โจ MODULES SPECIFIC TCL COMMANDS โจ
The Modules Package uses commands which are extensions to the "standard" Tool Command Language Tcl(n) package. Unless otherwise specified, the Module commands return the empty string. Some commands behave differently when a modulefile is loaded or unloaded. The command descriptions assume the modulefile is being loaded. ๐ซถ
๐งธ add-property name value
Associate module tag value to currently loading modulefile. Argument name is ignored. See module-tag command for more information on tags.
๐ซถ always-load [options] modulefile...
always-load [options] modulefile...
Load modulefile and apply the keep-loaded tag to it in order to avoid the automatic unload of this modulefile when modules dependent of it are unloaded.
always-load command accepts the following options:
--modulepathmodulepathlist--optional--tagtaglist
modulefile is declared as a requirement of currently loading module. This command acts as an alias of module load command. If more than one modulefile are specified, then this list acts as a Boolean AND operation, which means all specified modulefiles are required.
When the --optional option is set, each specified modulefile is declared as an optional requirement. A modulefile that cannot be loaded, will not stop the evaluation.
The --tag option accepts a list of module tags to apply to modulefile once loaded in addition to the keep-loaded tag. taglist corresponds to the concatenation of multiple tags separated by colon character. taglist should not contain tags inherited from modulefile state or from other modulefile commands. If module is already loaded, tags from taglist are added to the list of tags already applied to this module.
The --modulepath option accepts a list of modulepath. modulepathlist corresponds to the concatenation of multiple modulepaths separated by colon character. When this option is set, required modulefile should be located within one of the listed modulepaths. A path in this list may correspond to the first path elements of an actual modulepath (e.g., /path/to will match modulefiles located into the /path/to/modulefiles modulepath directory).
If an attempt to load modulefile is performed and --modulepath option is set, modulefile will be searched in the enabled modulepaths whose start match one of the specified paths and in the specified paths not matching any enabled modulepaths. For instance if this option is set to /path/to:/another/path and /path/to/modulefiles is currently the sole enabled modulepath, modulefile will be searched into /path/to/modulefiles and /another/path directories. ๐ฅ
๐ append-path [-d C|--delim C|--delim=C] [--duplicates] variable value...
append-path [-d C|--delim C|--delim=C] [--duplicates] variable value...
See prepend-path.
โ๏ธ break
This is not a Modules-specific command, it's actually part of Tcl, which has been overloaded similar to the continue and exit commands to have the effect of causing the module not to be listed as loaded and not affect other modules being loaded concurrently. All non-environment commands within the module will be performed up to this point. Processing will continue on to the next module on the command line unless if abort_on_error configuration option is enabled for running module sub-command. The break command will only have this effect if not used within a Tcl loop though. ๐ญ
An example: Suppose that a full selection of modulefiles are needed for various different architectures, but some of the modulefiles are not needed and the user should be alerted. Having the unnecessary modulefile be a link to the following notavail modulefile will perform the task as required.
#%Module
module-help {This module does nothing but alert the user}
module-help "that the [module-info name] module is not available"
module-whatis {Notifies user that module is not available.}
set curMod [module-info name]
if {[module-info mode load]} {
puts stderr "Note: '$curMod' is not available for [uname sysname]."
}
break
Modulefile usingbreakcommand when unloading may be unloaded anyway if--forceoption is set. To forbid the unload of a modulefile, it is recommended to tag itsuper-stickywithmodule-tagcommand.
๐ฆ chdir directory
Set the current working directory to directory.
๐ธ complete shell name body
Define shell completion for command name with specified body if shell is the current shell under which modulecmd.tcl was invoked. Body corresponds to argument options accepted by the shell command which defines completion. When a modulefile is unloaded, complete becomes uncomplete.
The following shells are supported: bash, tcsh, bash and fish. Please refer to the documentation of these shells to learn how to define completion. The command is ignored if an unsupported shell is specified.
๐
conflict modulefile...
conflict controls whether or not the modulefile will be loaded. The conflict command lists modulefiles which conflict with the current modulefile. If a list contains more than one modulefile, then each member of the list acts as a Boolean OR operation. Multiple conflict commands may be used to create a Boolean AND operation. If one of the requirements have not been satisfied, an error is reported and the current modulefile makes no changes to the user's environment. ๐
If an argument for conflict is a directory and any other modulefile from that directory has been loaded, then a conflict will occur. For example, specifying X11 as a conflict will stop X11/R4 and X11/R5 from being loaded at the same time.
The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
If the conflict_unload and auto_handling configuration options are enabled, conflict will attempt to unload all loaded modules that match specification. (see Automated module handling mechanisms in module). ๐ง
โญ continue
This is not a modules specific command but another overloaded Tcl command and is similar to the break or exit commands except the module will be listed as loaded as well as performing any environment or Tcl commands up to this point and then continuing on to the next module on the command line. The continue command will only have this effect if not used within a Tcl loop though.
๐ depends-on [options] modulefile...
depends-on [options] modulefile...
Alias of prereq-all command.
๐ depends-on-any [options] modulefile...
depends-on-any [options] modulefile...
Alias of prereq command.
exit [N]โ okay so heads up, this one is not a modules specific command ๐ it's another overloaded Tcl command, and it vibes a lot likebreakorcontinue. The difference? This one causes the immediate cessation of this module. Like, gone. Any additional modules sitting on the command line will not be evaluated โ even if theabort_on_errorconfiguration option is disabled for running module sub-command. This module and the subsequent modules will not be listed as loaded, and no environment commands will be performed in the current module. It's giving "we're done here" energy ๐extensions modulefile...โ alias of theprovidecommand โจfamily nameโ declares the loading modulefile as a member ofname's family. Only one member of a family could be loaded, and an error is raised when you attempt to load another member of the same family name. ๐ซ
family corresponds to the definition of a conflict on name and the definition of a module-alias name targeting the currently loading module.
In addition, the MODULES_FAMILY_<NAME> environment variable is defined and set to the currently loading module name minus version. This variable helps to know what module provides for the family name in the currently loaded environment. For instance, if loading modulefile foo/1.0 defines being member of the bar family, the MODULES_FAMILY_BAR will be set to the foo value. For compatibility, the LMOD_FAMILY_<NAME> environment variable is also defined and set to the same value as MODULES_FAMILY_<NAME>. ๐ซถ
name should be a non-empty string only containing characters that could be part of an environment variable name (i.e., [a-zA-Z0-9_]).
If the conflict_unload and auto_handling configuration options are enabled, an attempt to unload the loaded module that defines the same family is made (see Automated module handling mechanisms in module). ๐ฅ
getenv [--return-value] variable [value]โ returns the value of an environment variable ๐. Ifvariableis not defined,valueis returned if set, and an empty string is returned otherwise. Lowkey thegetenvcommand should be preferred over the Tcl global variableenvto query environment variables โ it's just better, iykyk.
When the modulefile is evaluated in display mode, getenv returns the variable name prefixed with a dollar sign (e.g., $variable) unless the --return-value option is set. When this option is set, the value of the environment variable or the defined fallback value is returned in display mode. โจ
getvariant [--return-value] variant [value]โ returns the value of the designated variant ๐ธ. Ifvariantis not defined,valueis returned if set, and an empty string is returned otherwise. Just likegetenv, thegetvariantcommand should be preferred over theModuleVariantTcl array to query a variant value โ main character behavior honestly.
When the modulefile is evaluated in display mode, getvariant returns the variant name enclosed in curly braces (e.g., {variant}) unless the --return-value option is set. When this option is set, the value of the variant or the defined fallback value is returned in display mode.
haveDynamicMPATHโ this command signals that a modulefile modifies theMODULEPATHenvironment variable ๐ฃ. It's useful when the modulefile conditionally updatesMODULEPATHand is processed by the Lmod tool.
Here in the Modules tool, this command is implemented as a no-operation, since the spider sub-command evaluates the modulefile in the context of the current user to determine whether MODULEPATH is updated. So it's basically decorative here, but it slays in Lmod ๐
hide-modulefile modulefileโ alias of themodule-hidecommand ๐hide-version modulefileโ alias of themodule-hidecommand ๐ (yep, same one, two names, iconic)is-avail modulefile...โ returns a true value if any of the listed modulefiles exists in the enabledMODULEPATHโ . If a list contains more than one modulefile, then each member acts as a boolean OR operation. And if an argument foris-availis a directory and a modulefile exists in that directory,is-availwould return a true value.
The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below). ๐ง
is-loaded [modulefile...]โ returns a true value if any of the listed modulefiles has been loaded, or if any modulefile is loaded in case no argument is provided ๐. If a list contains more than one modulefile, then each member acts as a boolean OR operation. If an argument foris-loadedis a directory and any modulefile from that directory has been loaded,is-loadedwould return a true value.
The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below). ๐
is-saved [collection...]โ returns a true value if any of the listed collections exists, or if any collection exists in case no argument is provided ๐. If a list contains more than one collection, then each member acts as a boolean OR operation.
If MODULES_COLLECTION_TARGET is set, a suffix equivalent to the value of this variable is appended to the passed collection name. In case no collection argument is provided, a true value will only be returned if a collection matching the currently set target exists. The way that detail matters fr fr ๐ญ
is-used [directory...]โ returns a true value if any of the listed directories has been enabled inMODULEPATH, or if any directory is enabled in case no argument is provided ๐. If a list contains more than one directory, then each member acts as a boolean OR operation.
A relative directory is resolved against the directory of the modulefile being evaluated and also against the current working directory, as a relative path entry in MODULEPATH refers to the latter. Yeah, both. Don't ask, it's just how it is ๐
lsb-release fieldโ provides certain Linux Standard Base (LSB) information ๐ง.lsb-releasewill invoke thelsb_release(1)command to get each field's information.
The field values are:
id: string id of distributorrelease: release number of distributioncodename: codename according to distribution release
module [sub-command] [sub-command-options] [sub-command-args]โ okay this is the big one, the main character of the section ๐ฅ. This command permits a modulefile toloadorunloadother modulefiles, or touseorunusemodulepaths. Just so we're clear: no checks are made to ensure that the modulefile does not try to load itself ๐ญ. Often it is useful to have a single modulefile that performs a number ofmodule loadcommands. For example, if every user on the system requires a basic set of applications loaded, then a core modulefile would contain the necessarymodule loadcommands.
The --not-req option may be set for the load, try-load, load-any, unload and switch sub-commands to inhibit the definition of an implicit prereq or conflict requirement onto specified modules. ๐ซถ
On try-load sub-command, modulefiles are considered optional prereq requirement. However an error is raised if they cannot be loaded โ unless if they are not found or forbidden.
The load-any sub-command loads one modulefile from the specified list. An error is obtained if no modulefile from the list can be loaded. No operation is performed if a modulefile from the list is found already loaded. โจ
The unload sub-command unloads one matching modulefile for each module specification provided as argument if the auto_handling or conflict_unload configuration options are disabled. When both options are enabled, unload removes all loaded modules matching each module specification. When both options are enabled, modules dependent of the unloaded modules are also unloaded. Otherwise, an error is raised if the module to unload has a dependent module loaded. โ ๏ธ Like, this is the part where you pay attention, bestie.
If the require_via configuration option is enabled, the use sub-command defines a requirement of modulefiles stored in the added modulepath onto the current modulefile.
The unuse sub-command accepts the --remove-on-unload, --noop-on-unload, --append-on-unload and --prepend-on-unload options to control the behavior to apply when the modulefile is unloaded. See remove-path for further explanation ๐.
The load, try-load, load-any and switch sub-commands accept the --tag option to apply specified tags to the modulefile once loaded. The option accepts a concatenation of multiple module tags separated by a colon character. taglist should not contain tags inherited from modulefile state or from other modulefile commands. If the module is already loaded, tags from taglist are added to the list of tags already applied to this module. ๐ท๏ธ
Heads up: command line switches--auto,--no-autoand--forceare ignored when passed to amodulecommand set in a modulefile. Like, they just don't do anything there. Periodt. ๐
Okay so quick vibe check, bestie: not all the sub-commands described in the Module Sub-Commands section of the module man page are available when module is used as a Modules specific Tcl command. Hereโs the availability map, and yes itโs giving very โknow your contextโ energy ๐
- Sub-commands available from
modulefileinterpretation:load,load-any,switch,try-load,unload,unuse,use- Also available but not recommended for use from regular
modulefile:aliases,avail,display,initadd,initclear,initlist,initprepend,initrm,initswitch,list,purge,reload,restore,save,savelist,saverm,saveshow,search,test,whatis
- Sub-commands available from initrc configuration file and sourced script file: same sub-commands available as for
modulefileandconfigsub-command. - Sub-commands available from
run-command(rc) file interpretation: none. literally zero. ๐ญ
๐ module-alias name modulefile
Assigns the modulefile to the alias name. This command should be placed in one of the modulecmd.tcl rc files in order to provide shorthand invocations of frequently used modulefile names. obsessed with the convenience factor, honestly โจ
The parameter modulefile may be either:
- a fully qualified modulefile with name and version
- a symbolic modulefile name
- another modulefile alias
๐ฅ module-forbid [options] modulefile...
Forbid use of modulefile. An error is obtained when trying to evaluate a forbidden module. This command should be placed in one of the modulecmd.tcl rc files.
module-forbid command accepts the following options:
--after datetime--before datetime--not-user {user...}--not-group {group...}--user {user...}--group {group...}--message {text message}--nearly-message {text message}
If --after option is set, forbidding is only effective after specified date time. Following the same principle, if --before option is set, forbidding is only effective before specified date time. Accepted date time format is YYYY-MM-DD[THH:MM]. If no time (HH:MM) is specified, 00:00 is assumed. --after and --before options are not supported on Tcl versions prior to 8.5.
If --not-user option is set, forbidding is not applied if the username of the user currently running modulecmd.tcl is part of the list of username specified. Following the same approach, if --not-group option is set, forbidding is not applied if current user is member of one of the groups specified. When both options are set, forbidding is not applied if a match is found for --not-user or --not-group.
If --user option is set, forbidding is applied only if the username of the user currently running modulecmd.tcl is part of the list of username specified. Following the same approach, if --group option is set, forbidding is applied only if current user is member of one of the groups specified. When both options are set, forbidding is applied if a match is found for --user or --group. If the same user name is set on both --user and --not-user options, --user prevails over --not-user. If the same group name is set on both --group and --not-group, --group prevails over --not-group.
Error message returned when trying to evaluate a forbidden module can be supplemented with the text message set through --message option.
If --after option is set, modules are considered nearly forbidden during a number of days defined by the nearly_forbidden_days modulecmd.tcl configuration option (see MODULES_NEARLY_FORBIDDEN_DAYS), prior reaching the expiry date fixed by --after option. When a nearly forbidden module is evaluated a warning message is issued to inform module will soon be forbidden. This warning message can be supplemented with the text message set through --nearly-message option.
If a module-forbid command applies to a modulefile also targeted by a module-hide --hard command, this module is unveiled when precisely named to return an access error.
Forbidden modules included in the result of avail or spider sub-commands are reported with a forbidden tag applied to them. Nearly forbidden modules included in the result of avail, list or spider sub-commands are reported with a nearly-forbidden tag applied to them. See Module tags section in module.
The parameter modulefile may leverage a specific syntax to finely select module version (see Advanced module version specifiers section below). It may also be a full path file name to precisely designate one module in a specific modulepath.
๐ธ module-help string
Defines a string which is displayed in case of the invocation of the module help command. This command takes no action on non-help modulefile evaluation.
Multi-word string should be enclosed in curly-braces or double-quotes. There may be more than one module-help command call in a modulefile. In which case each command call is reported as a separate line.
If a modulefile also defines a ModulesHelp procedure, the text defined with module-help is printed before running this procedure on help evaluation mode.
๐ฆ module-hide [options] modulefile...
Hide modulefile to exclude it from available module search or module selection unless query refers to modulefile by its exact name. This command should be placed in one of the modulecmd.tcl rc files.
module-hide command accepts the following options:
--soft|--hard--hidden-loaded--afterdatetime--beforedatetime--not-user{user...}--not-group{group...}--user{user...}--group{group...}
Okay so when the --soft option is set, the modulefile also gets set hidden โ but that hiding gets disabled when the root name of your search or selection query matches the module's root name. Bestie, this soft hiding mode is genuinely iconic: it lets you hide modulefiles from a bare module avail listing while โจkeepingโจ the ability to select that module for load through the regular resolution mechanism (i.e., no need to bust out the exact name just to select it). It's giving stealth mode but make it convenient. ๐
When the --hard option is set, the modulefile is also set hidden and it stays hidden even if a search or selection query refers to the modulefile by its exact name. No loopholes. Periodt. ๐ซ
When the --hidden-loaded option is set, the hidden state also applies to the modulefile when it is loaded. Hidden loaded modules do not appear on list sub-command output unless the --all option is set. Their loading or unloading informational messages are not reported unless the verbosity of Modules MODULES_VERBOSITY is set to a level higher than verbose. But hidden loaded modules are detected in any case by state query commands like is-loaded. So like, they're lurking but they're still there, iykyk. ๐
If the --after option is set, hiding is only effective after the specified date time. Following the same principle, if --before is set, hiding is only effective before the specified date time. Accepted date time format is YYYY-MM-DD[THH:MM]. If no time (HH:MM) is specified, 00:00 is assumed. --after and --before are not supported on Tcl versions prior to 8.5. โ
If the --not-user option is set, hiding is not applied if the username of the user currently running modulecmd.tcl is part of the list of username specified. Following the same approach, if --not-group is set, hiding is not applied if the current user is a member of one of the groups specified. When both options are set, hiding is not applied if a match is found for --not-user or --not-group. ๐
If the --user option is set, hiding is applied only if the username of the user currently running modulecmd.tcl is part of the list of username specified. Following the same approach, if --group is set, hiding is applied only if the current user is a member of one of the groups specified. When both options are set, hiding is applied if a match is found for --user or --group. If the same user name is set on both --user and --not-user, --user prevails over --not-user. If the same group name is set on both --group and --not-group, --group prevails over --not-group. The audacity of that tiebreak? Real. ๐
If the --all option is set on avail, aliases, whatis, search or spider sub-commands, hiding is disabled โ thus hidden modulefiles are included in module search. But heads up: hard-hidden modules (i.e., declared hidden with --hard) are not affected by --all and stay hidden even if the option is set. Also --all does not apply to module selection sub-commands like load. So in that context, a hidden module should always be referred to by its exact full name (e.g., foo/1.2.3 not foo) unless it has been hidden in --soft mode. And a hard-hidden module cannot be unveiled or selected in any case. Like, at all. Ever. ๐
The way the hiding levels stack is real: if severalmodule-hidecommands target the same modulefile, the strongest hiding level is retained. Which means if both a regular and a--softhiding command match a given module, regular hiding mode is considered. If both a regular and a--hardhiding command match a given module, hard hiding mode is retained. And a set--hidden-loadedoption is retained even if themodule-hidestatement on which it is declared is superseded by a strongermodule-hidestatement with no--hidden-loadedoption set. Loyalty! ๐ซถ
Hidden modules included in the result of avail or spider sub-commands are reported with a hidden tag applied to them. Hidden loaded modules included in the result of list sub-command are reported with a hidden-loaded tag applied to them. This tag is not reported on avail or spider sub-commands context. See the Module tags section in module(1). ๐ท๏ธ
The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select a module version (see the Advanced module version specifiers section below). Moreover, it may also be a full path file name to precisely designate one module in a specific modulepath. So many ways to point at one thing, and honestly? Versatile queen behavior. ๐
๐
module-info option [info-args]
Provide information about the modulecmd.tcl program's state. Some of the information is specific to the internals of modulecmd.tcl. option is the type of information to be provided, and info-args are any arguments needed. Think of it as a little peek behind the curtain, bestie. ๐ง
module-info alias name
Returns the full modulefile name to which the modulefile alias name is assigned. It's giving "who dis really is" energy. ๐
module-info command [commandname]
Returns the currently running modulecmd.tcl's command as a string if no commandname is given.
Returns 1 if modulecmd.tcl's command is commandname. commandname can be: load, unload, refresh, reload, source, switch, display, avail, aliases, list, whatis, search, purge, restore, help, test, try-load, load-any, mod-to-sh, reset, stash, stashpop or spider. Yeah, that's the whole squad. ๐
module-info loaded modulefile
Returns the names of currently loaded modules matching passed modulefile. The parameter modulefile might either be a fully qualified modulefile with name and version, or just a directory โ in which case all loaded modulefiles from the directory will be returned. The parameter modulefile may also be a symbolic modulefile name or a modulefile alias.
This command only returns the name and version of the designated loaded module. The defined variants of the loaded module are not included in the returned string. No variants, no extras, just the name and version. ๐
module-info mode [modetype]
Returns the current modulecmd.tcl's mode as a string if no modetype is given.
Returns 1 if modulecmd.tcl's mode is modetype. modetype can be: load, unload, remove (alias of unload), switch, refresh, nonpersist (alias of refresh), display, help, test, whatis or scan. Aliases included, we love a flexible king. โจ
module-info name
Return the name of the modulefile. This is not the full pathname for modulefile. See the Modules Variables section for information on the full pathname.
This command only returns the name and version of the currently evaluating modulefile. The defined variants are not included in the returned string. See the getvariant command or the ModuleVariant array variable to get defined variant values for the currently evaluating modulefile. So if you want the variants, go ask them directly. ๐
module-info shell [shellname]
Return the current shell under which modulecmd.tcl was invoked if no shellname is given. The current shell is the first parameter of modulecmd.tcl, which is normally hidden by the module alias.
If a shellname is given, returns 1 if modulecmd.tcl's current shell is shellname, returns 0 otherwise. shellname can be: sh, bash, ksh, zsh, csh, tcsh, fish, cmd, pwsh, tcl, perl, python, ruby, lisp, cmake, r. A whole roster, tbh. ๐
module-info shelltype [shelltypename]
Return the family of the shell under which modulefile was invoked if no shelltypename is given. As of module-info shell, this depends on the first parameter of modulecmd.tcl. The output reflects a shell type determining the shell syntax of the commands produced by modulecmd.tcl.
If a shelltypename is given, returns 1 if modulecmd.tcl's current shell type is shelltypename, returns 0 otherwise. shelltypename can be: sh, csh, fish, cmd, pwsh, tcl, perl, python, ruby, lisp, cmake, r. Slightly shorter list than shell โ because families, not individuals. ๐ธ
module-info specified
Return the module designation (name, version and variants) specified that led to current modulefile evaluation. It's literally what you asked for, verbatim. ๐โโ๏ธ
module-info symbols modulefile
Returns a list of all symbolic versions assigned to the passed modulefile. The parameter modulefile might either be a fully qualified modulefile with name and version, another symbolic modulefile name, or a modulefile alias. All the aliases, all the lore. ๐ฎ
module-info tags [tag]
Returns all tags assigned to the currently evaluated modulefile as a list of strings if no tag name is given (see the Module tags section in module(1)).
When tags are assigned to specific module variants, they are returned only if this variant is the one currently evaluated. Picky? Maybe. Correct? Absolutely. ๐
Returns 1 if one of the tags applying to the currently evaluated modulefile is tag. Returns 0 otherwise.
module-info type
Returns either C or Tcl to indicate which module command is being executed โ either the C version or the Tcl-only version โ to allow the modulefile writer to handle any differences between the two. And yes, you do have to handle both. ๐ญ
module-info usergroups [name]
Returns all the groups the user currently running modulecmd.tcl is member of as a list of strings if no name is given.
Returns 1 if one of the groups the current user running modulecmd.tcl is a member of is name. Returns 0 otherwise.
If the Modules Tcl extension library is disabled, the id(1) command is invoked to fetch groups of the current user. Backup plan behavior, honestly. ๐ซก
module-info username [name]
Returns the username of the user currently running modulecmd.tcl as a string if no name is given.
Returns 1 if the username of the current user running modulecmd.tcl is name. Returns 0 otherwise.
If the Modules Tcl extension library is disabled, the id(1) command is invoked to fetch the username of the current user. Same fallback, same energy. โญ
module-info version modulefileโ hands you the physical module name + version behind a symbolic version modulefile. Thatmodulefilearg can be a fully qualified one (name and version), another symbolic modulefile name, or a modulefile alias. ๐
module-tag [options] tag modulefile...
Associates tag with the modulefile(s) you name. This tag info gets reported alongside the modulefile in the avail, list, and spider sub-commands (peep the Module tags section in module). You can also query tag info mid-modulefile-evaluation with the module-info tags modulefile command. Lowkey important: module-tag commands belong in one of the modulecmd.tcl rc files. โจ
module-tag accepts these options:
--not-user {user...}--not-group {group...}--user {user...}--group {group...}
If --not-user is set, the tag is not applied when the username of whoever's running modulecmd.tcl is in the list of usernames you gave. Same energy for --not-group: tag isn't applied if the current user is a member of any of the listed groups. Set both, and the tag is not applied if a match turns up for --not-user or --not-group.
If --user is set, the tag is applied only when the username of the person running modulecmd.tcl is in your list. Same deal for --group: tag applies only if the current user is in one of the listed groups. Set both and the tag applies if there's a match for --user or --group. If the same user name shows up in both --user and --not-user, --user wins over --not-user. If the same group name shows up in both --group and --not-group, --group wins over --not-group. (Periodt, that's the tiebreak.) ๐
The modulefile parameter can also be a symbolic modulefile name or a modulefile alias. It can also use a special syntax to finely pick a module version (see the Advanced module version specifiers section below). And it can even be a full path file name to precisely designate one module in a specific modulepath. ๐ฏ
Tags inherited from other modulefile commands or module states cannot be set with module-tag โ try it and you get an error back. Those special tags are: auto-loaded, forbidden, hidden, hidden-loaded, loaded, nearly-forbidden and warning. ๐
When tag equals sticky or super-sticky, the designated modulefile gets defined as a Sticky module.
When tag equals keep-loaded, the designated modulefile is not automatically unloaded when it's been auto-loaded and its dependent modules are getting unloaded. ๐ซถ
module-version modulefile version-name...
Assigns the symbolic version-name to the modulefile. Put this one in one of the modulecmd.tcl rc files so you can get shorthand invocations of modulefile names you use all the time.
The special version-name default specifies the default version used for module commands when no specific version is given. This replaces the definitions made in the .version file in former modulecmd.tcl releases. ๐
The modulefile parameter can be either:
- a fully or partially qualified modulefile with name / version. If name is
.(dot) then the current directory name is assumed to be the module name. (Use this for deep modulefile directories.) - a symbolic modulefile name
- another modulefile alias
module-virtual name modulefile
Assigns the modulefile to the virtual module name. Place this command in rc files to define virtual modules. ๐ฆ
A virtual module stands for a module name associated to a modulefile. The modulefile is the script interpreted when loading or unloading the virtual module โ the one that appears, or can be found, under its virtual name.
The modulefile parameter is the relative or absolute file location of a modulefile.
module-warn [options] --message {text message} modulefile...
Prints a warning message when the modulefile is evaluated. This command can live in one of the modulecmd.tcl rc files or inside modulefiles. The warning fires when the modulefile is evaluated in load, display, test, help. ๐ญ
module-warn accepts these options:
--after datetime--before datetime--not-user {user...}--not-group {group...}--user {user...}--group {group...}
If --after is set, the warning is only effective after the specified date time. Same principle for --before: warning only effective before the specified date time. Accepted date time format is YYYY-MM-DD[THH:MM]. If no time (HH:MM) is specified, 00:00 is assumed. Heads up: --after and --before are not supported on Tcl versions prior to 8.5. ๐
If --not-user is set, the warning is not applied when the username of whoever's running modulecmd.tcl is in the list you gave. Same approach with --not-group: warning not applied if the current user is a member of one of the listed groups. Set both and the warning is not applied if a match is found for --not-user or --not-group.
If --user is set, the warning is applied only if the username of the person running modulecmd.tcl is in your list. Same approach with --group: warning applied only if the current user is a member of one of the listed groups. Set both and the warning is applied if a match is found for --user or --group. If the same user name is set on both --user and --not-user, --user prevails over --not-user. If the same group name is set on both --group and --not-group, --group prevails over --not-group. โญ
Modules in warning that show up in the results of the avail, list or spider sub-commands get reported with a warning tag applied to them. Check the Module tags section in module for the full tea. ๐
The modulefile parameter may use a special syntax to finely select a module version (see the Advanced module version specifiers section below). It may also be a full path file name to precisely designate one module in a specific modulepath.
module-whatis string
Defines a string that gets displayed when you invoke the module whatis command. A modulefile can have more than one module-whatis line, bestie โ stack 'em. This command takes no actions on load, display, etc. invocations of modulecmd.tcl. ๐ธ
The string parameter has to be wrapped in double-quotes if there's more than one word in it. Words are defined as being separated by whitespace characters (space, tab, cr).
modulepath-ignore pattern...
Ignores files and directories that match pattern while walking down modulepath content looking for modulefiles. Ignored elements are handled like they straight-up don't exist: they're not checked, not walked down, not reported, and not recorded in the modulepath cache file. ๐ง
pattern follows the same syntax and behavior as git does with .gitignore files:
- A pattern without a slash (except an optional trailing one) matches files or directories at any depth below the directory of the rc file defining it.
- A pattern with a slash at its start or in its middle is relative to the directory of the rc file defining it.
- A pattern ending with a slash only matches directories.
*matches anything except a slash.?matches any single character except a slash.[...]matches one character from a range or class.- A leading
**/means match in any directory. A trailing/**matches everything inside the designated directory.a/**/bmatches with zero or more intermediate directories. - A pattern starting with
!negates a previous match: the element is re-included. You can't re-include an element if one of its parent directories is ignored. - When several patterns match an element, the last matching pattern decides.
When defined in a .modulerc file located within a modulepath directory, patterns are relative to the directory of this rc file. When defined in a global or user rc file, patterns apply to every modulepath, relatively to their root directory. ๐ฅ
The .modulerc and .version files of walked-through directories are exempt from ignore matching.
modulepath-ignore definitions should not be conditional: ignored elements are excluded from the modulepath cache file when it's built, so patterns have to be static to get consistent results whether cache is used or not. (No cap, keep it static.)
The modulepath_ignore configuration option, enabled by default, controls whether modulepath-ignore definitions are applied. โ๏ธ
modulepath-label directory label
Assigns a label string to a modulepath directory. This label is used in avail, whatis, search and spider output to refer to the modulepath. ๐ท๏ธ
The directory parameter is a fully or partially qualified modulepath. If directory is . (dot) then the current directory of the modulerc file defining this command is assumed.
prepend-path [-d C|--delim C|--delim=C] [--duplicates] variable value...โ bestie, this one appends or prependsvalueto an environment variable. The variable is a colon-delimited (or delimiter-delimited) list, likePATH=directory:directory:directory. Default delimiter is a colon:, but you can pass literally any character you want with the--delimoption. Like, you could use a space instead (which means you'll need to handle it specially in Tcl by wrapping it in" "or{ }). A space, however, can not be specified with the--delim=Cform. Rude, I know. ๐
A reference-counter environment variable is also set so the system knows how many times value has been added to variable when it gets added more than once. This counter variable is named by prefixing variable with __MODULES_SHARE_ <#envvar-__MODULES_SHARE_-VAR>.
When value is already defined in variable, it is not added again, and it does not get moved to the end or the beginning of variable. The exception is when the --duplicates option is set, in which case value is added again to variable. No cap.
If variable isn't set yet, it gets created. And when a modulefile is unloaded, append-path and prepend-path literally become remove-path. Iconic behaviour, honestly.
If value corresponds to the concatenation of multiple elements separated by the colon (or delimiter) character, each element is treated separately.
Your provided value is used as-is. If you need any path resolution, you gotta do it inside the modulefile itself. And be careful when you include characters that have special meanings in the shell context (like ~), because the shell might expand those paths automatically โ and that can prevent the corresponding entries from being properly removed when the modulefile is unloaded. ๐
If the variable is MODULEPATH <#envvar-MODULEPATH> and the require_via <#mconfig-require_via> configuration option is activated, the modulefile is considered a dependency by the loaded modulefiles stored in the added modulepaths.
If a link is defined for variable through the linked_envvars <#mconfig-linked_envvars> configuration option, the same prepend-path command is applied to all the associated environment variables. Group chat energy fr fr.
And if an initial value is defined for the variable through the init_envvars <#mconfig-init_envvars> configuration option, that value is assigned before the modification is applied โ but only when the variable isn't already set.
๐ธ prereq
prereq [options] modulefile...
Okay so prereq controls whether or not the modulefile will be loaded at all. It lists the modulefiles that must have been previously loaded before the current modulefile will load. If a list contains more than one modulefile, then each member of the list acts as a Boolean OR operation. Multiple prereq commands may be used to create a Boolean AND operation. And if one of the requirements hasn't been satisfied? An error is reported, and the current modulefile makes no changes to the user's environment. Zero. Nothing. ๐
If an argument for prereq is a directory and any modulefile from that directory has been loaded, then the prerequisite is met. For example, specifying X11 as a prereq means that any version of X11, X11/R4 or X11/R5, must be loaded before proceeding.
The modulefile parameter may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see the Advanced module version specifiers section below, bestie โ iykyk).
The prereq command accepts the following options:
--modulepathmodulepathlist--optional--tagtaglist
When the --optional option is set, the whole list of specified modulefiles is declared as an optional requirement list. Evaluation is not stopped if no modulefile from the list is loaded. Chill vibes.
If the auto_handling <#mconfig-auto_handling> configuration option is enabled, prereq will attempt to load the specified modulefile if it's not found loaded yet (see Automated module handling mechanisms <#modules-auto-handling> in module <#module-1>).
The --tag option accepts a list of module tags to apply to the modulefile once it's loaded. taglist corresponds to the concatenation of multiple tags separated by the colon character. taglist should not contain tags inherited from modulefile state or from other modulefile commands. If the module is already loaded, the tags from taglist are added to the list of tags already applied to this module. ๐
The --modulepath option accepts a list of modulepath. modulepathlist corresponds to the concatenation of multiple modulepaths separated by the colon character. When this option is set, the required modulefile should be located within one of the listed modulepaths. A path in this list may correspond to the first path elements of an actual modulepath (e.g., /path/to will match modulefiles located in the /path/to/modulefiles modulepath directory).
If an attempt to load modulefile is performed and the --modulepath option is set, modulefile will be searched in the enabled modulepaths whose start matches one of the specified paths, and in the specified paths not matching any enabled modulepaths. For instance, if this option is set to /path/to:/another/path and /path/to/modulefiles is currently the sole enabled modulepath, modulefile will be searched in the /path/to/modulefiles and /another/path directories. The way that actually works is so satisfying ngl โจ
๐ฆ prereq-all
prereq-all [options] modulefile...
Declares the modulefile as a requirement of the currently loading module. This command acts as an alias of the prereq command. But here's the twist โ if more than one modulefile is specified, then this list acts as a Boolean AND operation, which means all the specified modulefiles are required. All of them. Every single one. ๐
The prereq-all command accepts the following options:
--modulepathmodulepathlist--optional--tagtaglist
When the --optional option is set, each specified modulefile is declared as an optional requirement. A modulefile that cannot be loaded will not stop the evaluation. We love a forgiving queen. ๐ซถ
๐ง prereq-any
prereq-any [options] modulefile...
Literal alias of the prereq command. That's it. That's the whole vibe check. ๐
โญ provide
provide modulefile...
Defines each specified modulefile as a module alias of the currently evaluating module. The provide command helps you declare the additional elements included in a modulefile. So extra, so generous.
The provide command should be paired with a conflict command if the specified alias should be uniquely provided in the currently loaded environment. Don't skip that step, bestie.
Note: a module alias defined using theprovidecommand will not be recognized during module resolution. It's recommended to use themodule-aliascommand to define an alias that points to the default resolution target. Consider yourself warned. ๐ญ
๐ pushenv
pushenv variable value
Sets the environment variable to value and saves the previous value of variable so it can be restored when the modulefile is unloaded. Just like the setenv modulefile command, changes made to variable with pushenv are applied to variable in Tcl's env array to update the environment variable value in the current evaluation context.
When the modulefile is unloaded, the value saved from the pushenv command of this modulefile is removed from the saved-value stack list. variable is then set to the remaining value on top of the stack โ or it's unset if the stack becomes empty. It's giving undo button realness. ๐
The saved value stack list for variable is stored in an environment variable which is named by prefixing variable with __MODULES_PUSHENV_ <#envvar-__MODULES_PUSHENV_-VAR>.
If a link is defined for variable through the linked_envvars <#mconfig-linked_envvars> configuration option, the same pushenv command is applied to all associated environment variables. Slay, linked behaviour.
๐ puts
puts [-nonewline] [channelId] string
Writes the characters given by string to the channel given by channelId. This command is part of the regular set of Tcl commands, but it's been enhanced with specific features in the modulefile evaluation context. See the puts(n) Tcl man page for the basic description of this command โ the specific features for the modulefile evaluation context are described in the rest of this section. โจ
Content written to the stderr channel is rendered as an output message produced by the modulefile. Content written to the stdout channel is rendered as a shell command evaluated in the user's current shell environment. Content sent to stdout is spooled so it gets rendered after the environment changes made by the modulefile. Order matters, bestie!
When channelId equals prestdout, the content is rendered as a shell command evaluated in the current shell environment. This content is spooled and rendered prior to any other environment changes. Sneaky little early bird. ๐ฆ
When channelId equals log, content is sent to the log system through the defined logger <#mconfig-logger> command.
๐ remove-path
remove-path [options] variable value...
[--append-on-unload|--prepend-on-unload value...]
Removes value from the colon-delimited (or delimiter-delimited) list in variable. Byeee ๐
The remove-path command accepts the following options:
-d C,--delim C,--delim=C--index--glob--remove-on-unload,--noop-on-unload,--append-on-unload,--prepend-on-unload
See prepend-path or append-path for further explanation of using an arbitrary delimiter. Every string between colons (or delimiters) in variable is compared to value. If the two match, value is removed from variable โ but only if its reference counter is equal to 1 or unknown. Math checks out, no cap.
When the --index option is set, value refers to an index in the variable list. The string element pointed to by this index is set for removal. Target acquired. ๐ฏ
When the --glob option is set, value refers to a glob-style pattern which is matched against the values in variable to find the ones to remove. The * character in value matches any sequence of characters, including a null string. The ? character in value matches any single character. See the string(n) Tcl command for the full list of special characters. Wildcard slay. ๐ธ
Okay so back to the unload side of things, because that's where it gets spicy ๐ถ๏ธ โ when the modulefile is unloaded, literally nothing happens by default, or if the --noop-on-unload option is set. If --remove-on-unload is set, the value gets removed. If --append-on-unload is set, it appends back the value that got removed at load time (or a specific value, if one was set). If --prepend-on-unload is set, it prepends back the value removed at load time (or a specific value, if any was set).
๐จ heads up bestie: these options cannot be set if the --index option is also set. And --append-on-unload and --prepend-on-unload cannot be set if --glob is also set. Like, they just can't coexist, periodt.
Now, the reference counter of a value in a variable tracks how many times that value has been added to the variable. This info lives in the environment variable __MODULES_SHARE_variable. When something tries to remove a value from the variable, the relative reference counter gets checked, and the value is only actually removed if the counter equals 1 or isn't defined at all. Otherwise the value stays put in the variable and the reference counter just goes down by 1. And if the counter equals 1 after being decremented, both the value and its counter get yeeted out of the reference counter variable. โจ
If the value is actually a concatenation of multiple elements separated by the colon (or delimiter) character, each element gets treated separately, one by one.
An error is raised if the value equals the delimiter character itself. ๐
If a link is defined for the variable through the linked_envvars configuration option, the same remove-path command gets applied to all the associated environment variables too. Teamwork!
And if an initial value is defined for the variable through the init_envvars configuration option, the variable gets unset when โ after the modification โ its value matches the configured initial value and no explicit reference counter is defined.
report string
Outputs string as a message during modulefile evaluation. cute little status update, love that for you ๐ฌ
reportError string
Outputs string as an error message during modulefile evaluation and raises the error count. Important: reportError does not abort modulefile evaluation. If you actually want to abort the evaluation and emit an error message, use the error(n) Tcl command. โ ๏ธ
reportWarning string
Outputs string as a warning message during modulefile evaluation. gentle nudge, no drama ๐ซถ
require-fullname
Aborts the load evaluation of the modulefile if the name specified to designate it is not the fully qualified one. Module aliases and symbolic version names count as fully qualified names โ the one exception is the default symbol. iykyk ๐
set-alias alias-name alias-string
Sets an alias named alias-name in the user's environment to the string alias-string. For some shells, aliases just aren't possible and the command has no effect (check the Shell support section). When a modulefile is unloaded, set-alias becomes unset-alias. ๐
set-function function-name function-string
Creates a function named function-name in the user's environment with the function body function-string. For some shells, functions aren't possible and the command has no effect (again, see the Shell support section). When a modulefile is unloaded, set-function becomes unset-function. ๐ฆ
setenv [--set-if-undef] variable value
Sets the environment variable variable to value. The setenv command also changes the process' environment. A reference using Tcl's env associative array will see changes made with the setenv command. But changes made using Tcl's env associative array will NOT change the user's environment variable the way the setenv command does โ an environment change made that way only affects the module parsing process. setenv is also useful for changing the environment prior to the exec or system command.
When a modulefile is unloaded, setenv becomes unsetenv.
๐ real talk: if the environment variable had already been defined, it gets overwritten while loading the modulefile. A subsequent unload will unset the environment variable โ the previous value cannot be restored! (Unless you handle it explicitly, or you use thepushenvmodulefile command instead ofsetenv. ๐)
When the --set-if-undef option is set, the environment variable is defined when the modulefile is loaded only if it's not yet defined. Conditional slay.
Any newline character in value gets chopped off if you're using csh or tcsh shells.
If a link is defined for the variable through the linked_envvars configuration option, the same setenv command gets applied to all associated environment variables. โจ
source-sh [--ignore eltlist] shell script [arg...]
Evaluates script with shell using the defined arguments, to figure out what environment changes it makes. Those changes โ obtained by comparing the environment before and after the script evaluation โ are then translated into corresponding modulefile commands, which get applied during modulefile evaluation just as if they'd been written directly in it. icon behavior honestly ๐ฅ
When the modulefile is unloaded, the environment changes that were made get reversed by evaluating (in the unload context) the resulting modulefile commands, which were recorded in the __MODULES_LMSOURCESH environment variable at load time.
Tracked changes include: environment variables, shell aliases, shell functions, shell completions, and the current working directory. ๐
Changes made on environment variables intended for Modules' private use (e.g., LOADEDMODULES, _LMFILES_, __MODULES_*) are ignored. not your business, respectfully ๐
shell can be given as a command name or as a fully qualified pathname. These shells are supported: sh, dash, csh, tcsh, bash, ksh, ksh93, zsh and fish.
shell can also be set to bash-eval. In this mode, the bash shell script is not sourced โ instead, the output resulting from its execution is evaluated to determine the environment changes it makes. different vibe, same goal โจ
The --ignore option accepts a list of shell elements whose changes made by the script should be ignored. eltlist is the concatenation of multiple shell elements separated by the colon character. Accepted shell elements are: envvar, alias, function, chdir and complete.
๐ Note:shellis run in non-interactive mode without loading any shell configuration or profile. As a result,scriptdoes not have access to transient definitions that are only available in interactive sessions or profile files โ stuff like shell aliases, functions, or completion settings. ๐ญ
system string
Runs the string command through a shell. On Unix, the command is passed to the /bin/sh shell, whereas on Windows it's passed to cmd.exe. modulecmd.tcl redirects stdout to stderr, since stdout would get parsed by the evaluating shell. The exit status of the executed command is returned. ๐ซก
uname field
Provides lookup of system information. Most field info is retrieved from the tcl_platform array (see the tclvars(n) man page). uname returns the string unknown if the information is unavailable for the field.
uname will invoke the uname(1) command to get the operating system version, and domainname(1) to figure out the name of the domain. ๐
The field values are:
sysname: the operating system namenodename: the hostnamedomain: the name of the domainrelease: the operating system releaseversion: the operating system versionmachine: a standard name that identifies the system's hardware
uncomplete name
Unsets completion for the command name in the user's environment. When a modulefile is unloaded, no operation is performed. bye completion ๐
These shells are supported: bash, tcsh and fish.
unset-alias alias-name
Unsets the alias named alias-name in the user's environment. poof, gone โจ
unset-function function-name
Removes the function named function-name from the user's environment. also poof ๐จ
unsetenv [options] variable [value]
Unsets the environment variable variable. When a modulefile is unloaded, no operation is performed โ unless an optional value is defined, in which case variable gets set to value. The unsetenv command changes the process' environment just like setenv. ๐
If the --noop-on-unload option is set, no operation is performed when the modulefile is unloaded. If the --unset-on-unload option is set, the environment variable also gets unset when the modulefile is unloaded. These behaviors apply even if an optional value is defined. read that twice bestie ๐
If a link is defined for the variable through the linked_envvars configuration option, the same unsetenv command gets applied to all associated environment variables.
variant [--boolean] [--default value] name [value...]
Declares a module variant name with a list of accepted values, and instantiates it in the ModuleVariant array variable. ๐
The variant's value is selected through the module designation that leads to the modulefile evaluation. (See the Advanced module version specifiers section to learn how variants can be specified.)
The selected variant value gets transmitted to the evaluating modulefile. A value must be specified for the variant name, and it must correspond to a value in the accepted value list if such a list is defined. Otherwise an error is raised. There's one exception: if the modulefile is evaluated in display mode, no error is raised if no value is specified for a given variant, and the variant just isn't instantiated in the ModuleVariant array variable. And when no list of accepted values is defined, the variant can be set to any value at all. free spirit ๐ธ
When the --default option is set, the variant name gets set to the value associated with this option, in case no value is specified for the variant in the module designation.
If the --boolean option is set, congrats, your variant is officially a Boolean variant ๐ and you should not define a list of accepted values for it โ that's just not its era. Every value Tcl recognizes as Boolean gets the green light: 1, true, t, yes, y, on, 0, false, f, no, n, or off. Boolean variants get instantiated in ModuleVariant using Tcl's canonical Boolean form (so like, 0 or 1, periodt).
A variant that is not defined as a Boolean variant cannot declare Boolean values in its accepted value list โ the one exception is the 0 and 1 integers. Do it anyway and an error gets raised. No cap.
Variant names are picky in the cutest way ๐
they should only be made of characters from the A-Za-z0-9_- range. Also: a variant name can't start with a - (minus) character, and the whole name can't just be a number. Break these rules โ error raised, sorry bestie.
Oh and one more thing: a variant cannot be named version. Try it and an error gets raised. That name is taken, it's giving main character already.
versioncmp version1 version2
Compare version string version1 against version string version2. Returns -1, 0, or 1 โ respectively meaning version1 is less than, equal to, or greater than version2. Simple as, honestly ๐
x-resource [resource-string|filename]
Merge resources into the X11 resource database โจ (yes, that X11 resource database โ the thing that controls how X11 apps look and behave). The command will attempt to read resources from filename. But if the argument isn't a valid file name, then the string gets interpreted as a resource instead. Either filename or resource-string is then passed down to the xrdb(1) command.
Modulefiles that use this command should, in most cases, contain one or more x-resource lines โ each one defining one X11 resource. The DISPLAY environment variable should be properly set and the X11 server should be accessible. And if x-resource can't manipulate the X11 resource database? The modulefile exits with an error message. ๐ญ
Examples, bestie:
x-resource /u2/staff/leif/.xres/Ileaf
The content of the Ileaf file is merged into the X11 resource database.
x-resource [glob ~/.xres/ileaf]
The Tcl glob function is used to have the modulefile read different resource files for different users. Personalized, we love to see it ๐ซถ
x-resource {Ileaf.popup.saveUnder: True}
Merge the Ileaf resource into the X11 resource database. Done and done.
๐ฆ modulefiles vs. rc files, a vibe check ๐ฆ
Modulefiles and run-command (rc) files are interpreted differently. Only a limited number of the Modules specific Tcl commands are available for rc file interpretation, because those files are meant to set parameters for modulefiles (think: defining alias, hiding, tagging, etc.) and not to change the user environment. Groundbreaking distinction, ik.
So here's who gets what:
- Commands available from modulefile interpretation: All the Modules specific and standard Tcl commands.
- Commands available from run-command (rc) file interpretation:
getenv,hide-modulefile,hide-version,is-loaded,is-used,lsb-release,module-alias,module-forbid,module-hide,module-info,module-tag,module-version,module-virtual,module-warn,modulepath-ignore,modulepath-label,system,uname,versioncmpand standard Tcl commands.
Note: Global and user run-command files are interpreted like modulefiles and benefit from all Modules specific Tcl commands. However, it is not advised to perform environment changes from such files. Like, just don't. ๐
๐ MODULES VARIABLES ๐
ModulesCurrentModulefile
Holds the full pathname of the modulefile being interpreted. Your "you are here" map, basically ๐
ModulesVersion
This one can be set in a .version file to designate the name of the modulefile version which should be considered as default in the current directory (peep the Locating Modulefiles section below ๐).
ModuleTool
Contains the name of the module implementation currently in use. For this implementation, the value is set to Modules.
ModuleToolVersion
Contains the version of the module implementation currently in use. For this version of Modules, the value is set to 5.7.0. Iconic number, no notes ๐ฅ
ModuleVariant
The ModuleVariant array variable holds one element entry for each defined variant, tied to that variant's value โ like, the $ModuleVariant(foo) syntax corresponds to the value of variant foo if it's defined. Access an undefined variant in the ModuleVariant array and you get a Tcl evaluation error. ๐ฌ So when you don't know whether a variant is even a thing, use the getvariant command to retrieve a variant value instead. Much safer energy.
Wanna see the list of currently defined variants? Grab it with the [array names ModuleVariant] Tcl code. Slay.
๐ LOCATING MODULEFILES ๐
Okay bestie, so when modulecmd.tcl is out here looking for a modulefile, it searches every single directory in MODULEPATH โ literally every one. A directory in MODULEPATH can have an arbitrary number of sub-directories, no cap. If the user names a modulefile to be loaded which is actually a directory, the directory is opened and a search begins for an actual modulefile. First, modulecmd.tcl looks for a file with the name .modulerc in the directory. If this file exists, its contents will be evaluated as if it was a modulefile to be loaded. You may place module-version, module-alias and module-virtual commands inside this file. ๐
Additionally, before seeking for .modulerc files in the module directory, the global modulerc file and the .modulerc file found at the root of the modulepath directory are sourced, too. If a named version default now exists for the modulefile to be loaded, the assigned modulefile now will be sourced. Otherwise the file .version is looked up in the module directory.
If the .version file exists, it is opened and interpreted as Tcl code and takes precedence over a .modulerc file in the same directory. If the Tcl variable ModulesVersion is set by the .version file, modulecmd.tcl will use the name as if it specifies a modulefile in this directory. This will become the default modulefile in this case. ModulesVersion cannot refer to a modulefile located in a different directory. Like, that's the rule โ no sneaky cross-directory defaults.
If ModulesVersion is a directory, the search begins anew down that directory. If the name does not match any files located in the current directory, the search continues through the remaining directories in MODULEPATH.
Every .version and .modulerc file found is interpreted as Tcl code. The difference is that .version only applies to the current directory, and the .modulerc applies to the current directory and all subdirectories. Changes made in these files will affect the subsequently interpreted modulefile.
If a .modulecache file is found at the root of a modulepath directory, this file is interpreted as Tcl code to learn all .modulerc, .version and modulefiles available. Modulepath content is read from module cache file. Modulepath directory is only walked through to check if limited access modulefiles or directories are available to current user.
If no default version may be figured out, an implicit default is selected when this behavior is enabled (see MODULES_IMPLICIT_DEFAULT in module). If disabled, module names should be fully qualified when no explicit default is defined for them, otherwise no default version is found and an error is returned. If enabled, then the highest numerically sorted modulefile, virtual module or module alias under the directory will be used. The dictionary comparison method of the lsort(n) Tcl command is used to achieve this sort. If highest numerically sorted element is an alias, search continues on its modulefile target.
For example, it is possible for a user to have a directory named X11 which simply contains a .version file specifying which version of X11 is to be loaded. Such a file would look like:
#%Module
set ModulesVersion R4
The equivalent .modulerc would look like:
#%Module
module-version ./R4 default
If the extended default mechanism is enabled (see MODULES_EXTENDED_DEFAULT in module) the module version specified is matched against starting portion of existing module versions, where portion is a substring separated from the rest of version string by . or - characters.
When the implicit default mechanism and the Advanced module version specifiers are both enabled, a default and latest symbolic versions are automatically defined for each module name (also at each directory level in case of deep modulefile). Unless a symbolic version, alias, or regular module version already exists for these version names.
Every file in searched directories is checked to see if it begins with the Modules magic cookie (i.e., #%Module file signature) to determine if it is a modulefile (see DESCRIPTION section). When the mcookie_check configuration is set to eval, this check is skipped and all files in search directories are considered modulefiles.
If user names a modulefile that cannot be found in the first modulepath directory, modulefile will be searched in next modulepath directory and so on until a matching modulefile is found. If search goes through a module alias or a symbolic version, this alias or symbol is resolved by first looking at the modulefiles in the modulepath where this alias or symbol is defined. If not found, resolution looks at the other modulepaths in their definition order.
When locating modulefiles, if a .modulerc, a .version, a directory or a modulefile cannot be read during the search it is simply ignored with no error message produced. Visibility of modulefiles can thus be adapted to the rights the user has been granted. Exception is made when trying to directly access a directory or a modulefile. In this case, the access issue is returned as an error message. So yeah โ silent skip unless you go straight at it, then it's an error.
Depending on their name, their file permissions or the use of specific modulefile commands, modulefile, virtual module, module alias or symbolic version may be set hidden which impacts available modules search or module selection processes (see Hiding modulefiles section below).
๐ HIDING MODULEFILES ๐
A modulefile, virtual module, module alias or symbolic version whose name or element in their name starts with a dot character (.) or who are targeted by a module-hide command are considered hidden. Hidden modules are not displayed or taken into account except if they are explicitly named (e.g., foo/1.2.3 or foo/.2.0 not foo). If module has been hidden with the --soft option of the module-hide command set, it is not considered hidden if the root name of the query to search it matches module root name (e.g., searching foo will return a foo/1.2.3 modulefile targeted by a module-hide --soft command). If module has been hidden with the --hard option of the module-hide command set, it is always considered hidden thus it is never displayed nor taken into account even if it is explicitly named. Periodt โ hard-hidden means hard-hidden. ๐
A modulefile, virtual module, module alias or symbolic version who are targeted by a module-hide --hard command and a module-forbid command or whose file access permissions are restricted are considered hard-hidden and forbidden. Such modules are not displayed or taken into account. When explicitly named for evaluation selection, such modules are unveiled to return an access error.
๐ Note
When themcookie_checkconfiguration is set toeval, file access permissions are not checked thus files with restricted permissions are included in search results but still lead to error if evaluated.
A symbolic version-name assigned to a hidden module is displayed or taken into account only if explicitly named and if module is not hard-hidden. Non-hidden module alias targeting a hidden modulefile appears like any other non-hidden module alias. Finally, a hidden symbolic version targeting a non-hidden module is displayed or taken into account only if not hard-hidden and explicitly named to refer to its non-hidden target.
The automatic version symbols (e.g., default and latest) are unaffected by hiding. Moreover when a regular default or latest version is set hidden, the corresponding automatic version symbol takes the left spot. For instance, if foo/default which targets foo/1.2.3 is set hard-hidden, the default automatic version symbol will be set onto foo/2.1.3, the highest available version of foo.
When loading a modulefile or a virtual module targeted by a module-hide --hidden-loaded command, this module inherits the hidden-loaded tag. Hidden loaded modules are not reported among list sub-command results.
If the --all option is set on avail, aliases, whatis, search or spider sub-commands, hidden modules are taken into account in search. Hard-hidden modules are unaffected by this option.
If the --all option is set on list sub-command, hidden loaded modules are included in result output.
A behavior equivalent to the use of the --all option is obtained on avail, list and spider sub-commands by adding the hidden element to the output configuration option controlling regular or terse reporting of these sub-commands: avail_output, avail_terse_output, list_output, list_terse_output, spider_output, spider_terse_output. โจ
โจ ADVANCED MODULE VERSION SPECIFIERS โจ
okay bestie, this is where it gets good. When the advanced module version specifiers mechanism is turned on (peep MODULES_ADVANCED_VERSION_SPEC in module), the way you specify a modulefile on Modules specific Tcl commands literally changes. After the module name, you can tack on a version constraint and variants. It's giving glow-up. ๐
๐ Version specifiers ๐
After the module name you can drop a version constraint, prefixed with the @ character. It can be glued straight onto the module name or separated from it with a space character. Either way, slay.
Constraints are how you refine which module version gets picked, and there are three flavors:
- a single version with the
@versionsyntax โ for instancefoo@1.2.3will select modulefoo/1.2.3 - a list of versions with the
@version1,version2,...syntax โ for instancefoo@1.2.3,1.10will match modulesfoo/1.2.3andfoo/1.10 - a range of versions with the
@version1:,@:version2and@version1:version2syntaxes โ for instancefoo@1.2:will select all versions of modulefoogreater than or equal to1.2,foo@:1.3will select all versions less than or equal to1.3, andfoo@1.2:1.3matches all versions between1.2and1.3including the1.2and1.3versions
โจ Pro tip era: advanced specification of a single version or a list of versions may benefit from turning the extended default mechanism on (see MODULES_EXTENDED_DEFAULT in module) so you can use an abbreviated notation like @1 to refer to more precise version numbers like 1.2.3. The characters . and - are considered version number separators when determining abbreviated versions. Range of versions, on its side, natively handles abbreviated versions. The upper bound may be less precise than the lower bound, and an abbreviated upper bound includes all versions that extend it โ provided they also satisfy the lower bound. No cap. ๐ซถ
Heads up babes: in order to be specified in a range of versions or compared to a range of versions, the version major element should correspond to a number. So like,10a,1.2.3, and1.fooare versions valid for range comparison, whereasdefaultorfoo.2versions are invalid for range comparison. ๐
Range of versions can also be specified inside a version list โ for instance foo@:1.2,1.4:1.6,1.8:. This kind of specification helps to exclude specific versions, like versions 1.3 and 1.7 in the previous example. Sneaky and iconic.
If the implicit default mechanism is also enabled (see MODULES_IMPLICIT_DEFAULT in module), a default and latest symbolic versions are automatically defined for each module name (also at each directory level for deep modulefiles). These automatic version symbols are defined unless a symbolic version, alias, or regular module version already exists for these default or latest version names. Using the mod@latest (or mod/latest) syntax ensures the highest available version will be selected. Obsessed with her. ๐
๐ฆ Variants ๐ฆ
After the module name, variants can be specified too. Module variants are alternative evaluation of the same modulefile. A variant is specified by associating a value to its name. This specification is then transmitted to the evaluating modulefile, which instantiates the variant in the ModuleVariant array variable when reaching the variant modulefile command declaring this variant.
Variant can be specified with the name=value syntax, where name is the declared variant name and value is the value this variant is set to when evaluating the modulefile.
Boolean variants can be specified with the +name syntax to set this variant on, and with the -name or ~name syntaxes to set this variant off.
Careful bestie ๐ญ โ the-namesyntax is not supported onmlcommand, because the minus sign already means to unload the designated module.
The ~name and +name syntaxes could also be defined appended to another specification word (e.g., the module name, version or another variant specification), whereas -name syntax must be the start of a new specification word. Read that twice, it matters. ๐
Boolean variants may also be specified with the name=value syntax. In that case value should be set to 1, true, t, yes, y or on to enable the variant, or it should be set to 0, false, f, no, n or off to disable the variant.
Shortcuts may be used to abbreviate variant specification. The variant_shortcut configuration option associates a shortcut character to a variant name. With a shortcut defined, variant could be specified with the <shortcut>value syntax. For instance, if character % is set as a shortcut for variant foo, the %value syntax is equivalent to the foo=value syntax. It's giving efficiency queen. ๐
Variant name should only be composed of characters part of the A-Za-z0-9_- range. Also, a variant name cannot start with - (minus) character and the overall name cannot just be a number.
Specific characters used in variant specification syntax cannot be used as part of the name or version of a module. These specific characters are +, ~, = and all characters set as variant shortcut. Exception is made for + and ~ characters if the string that follows after does not correspond to a valid variant name (e.g., name+, name++, name/version+1). ๐ธ
๐ DEPENDENCIES BETWEEN MODULEFILES ๐
okay so this is the part where modulefiles start having relationships โ very main character energy. a modulefile can express dependencies on other modulefiles, and there are exactly two flavors:
- pre-requirement โ the modulefiles you name here should be loaded before the modulefile that's expressing the requirement โจ
- conflict โ the modulefiles you name here should not be loaded, or else the modulefile expressing the conflict can't be loaded too ๐
Pre-requirement can be expressed with prereq, prereq-any, prereq-all, depends-on, depends-on-any, always-load, module load, module switch, module try-load or module load-any modulefile commands. Now here's the tea: when the auto_handling configuration option is disabled, the required modulefile has to be manually loaded prior to its dependent modulefile โ but only when it's expressed with prereq, prereq-any, prereq-all, depends-on or depends-on-any. For the other commands, or when auto_handling is enabled, those pre-required modulefiles get loaded automatically, no cap ๐ซถ
There's another form of pre-requirement too, and it's lowkey sneaky: it comes through the module use, append-path MODULEPATH, or prepend-path MODULEPATH modulefile commands, when the require_via configuration option is enabled. In that case, a modulefile that adds a modulepath is treated as a requirement for the modulefiles loaded from that path. This pre-requirement gets considered when such modules are already loaded, which helps keep things consistent when you try to unload a modulefile that enables a modulepath ๐ธ
Conflict, on the other hand, is expressed with conflict, family or module unload modulefile commands. When the auto_handling or conflict_unload configuration options are disabled, a conflicting loaded modulefile has to be manually unloaded prior to loading the modulefile that expresses such conflict โ that's when it's defined with conflict or family. It is automatically unloaded when expressed with module unload (unless dependent modulefiles are loaded), or if auto_handling and conflict_unload are both enabled ๐
And heads up: an error is raised when you try to load a module that's already loaded but with a different variant set or coming from a different modulepath. But if both options are enabled, the loaded module is automatically unloaded to satisfy the new set of variant or modulepath asked. slay, honestly ๐ฅ
ok bestie, listen: it is strongly advised to define dependencies prior to environment changes in a modulefile. like, put the deps first. periodt.
Dependency resolution should be done before any environment change to ensure the environment gets set in the same order whether pre-requirements are already loaded, or if they are automatically loaded when loading the modulefile which depends on them, or if all loaded modules are reloaded or refreshed. This is especially important when the modulefile updates an environment variable that's also altered by other modulefiles โ like PATH. Since the order of the path elements in such a variable defines priority, it's important that this order doesn't change depending on the way the modulefiles are loaded ๐
Moreover, when conflict_unload is enabled, a conflicting loaded modulefile is unloaded at the time the conflict, family or module unload command is evaluated. Environment changes made prior to this command by the loading modulefile are overridden by this unload when they affect variables also altered by the unloaded modulefile. For instance, a variable set by the loading modulefile ends up unset if it's also set by the unloaded modulefile. yeah. chaotic, but that's the rule ๐
module keeps environment consistent, which means a modulefile cannot be loaded if its requirements are not loaded, or if a conflicting module is loaded. In addition, a loaded module cannot be unloaded if other loaded modules depend on it. The automated module handling mechanisms attempt to solve the dependencies expressed by loading or unloading additional modulefiles ๐ฆ
When the --no-auto option is set on the module command when loading or unloading a modulefile, the automated module handling mechanisms are disabled and dependencies have to be solved manually โ and when dependencies are not satisfied, the modulefile fails to load or unload. rip ๐ญ
Adding the --not-req option when expressing dependencies in a modulefile with the module command will attempt to load or unload the designated modulefile, but it will not mark them as pre-requirement or conflict. sneaky but legal ๐
Adding the --optional option on prereq, prereq-any, prereq-all, depends-on, depends-on-any or always-load modulefile commands declares the pre-requirement as optional. If an optional pre-requirement is not found loaded or cannot be automatically loaded, the dependency expressed is yet considered satisfied โจ And when an optional requirement is loaded afterward, the dependent module will get automatically reloaded โ but only if the auto_handling configuration option is enabled ๐ง
By adding the --force option to the module command when loading or unloading a modulefile, the consistency checks are by-passed. This option cannot be used when expressing dependencies in modulefiles. And if a module has been force loaded whereas its requirements are not loaded, or whereas a conflicting module is also loaded, the user environment is said inconsistent โญ
Also note: a pre-requirement should be found in the loaded module list prior to its dependent module. The user environment is considered inconsistent if the pre-requirement module is found loaded after the dependent module, since the environment changes may have been done in the wrong priority order. ๐
When the user environment is considered inconsistent, the global operations achieved by refresh, reload and save sub-commands cannot perform. This mechanism is there to avoid the situation getting worse by re-evaluating all loaded modules or recording this environment ๐
And when the auto_handling configuration option is enabled, if a missing pre-requirement modulefile gets loaded, or a conflicting modulefile gets unloaded, the inconsistent loaded module will be automatically reloaded to make the user environment consistent again. self-healing queen behavior ๐
๐ MODULEFILE SPECIFIC HELP ๐
Users can request help about a specific modulefile through the module command. The modulefile can print helpful information or start help-oriented programs by defining a ModulesHelp subroutine ๐ That subroutine will be called when the module help modulefile command is used.
Help text may also be defined within the modulefile with the module-help command. Text defined that way is printed before evaluation of the ModulesHelp subroutine, if any ๐ธ
โจ MODULEFILE SPECIFIC TEST โจ
Users can request a test of a specific modulefile through the module command. The modulefile can perform some sanity checks on its own definition or on its underlying programs by defining a ModulesTest subroutine ๐ฆ That subroutine will be called when the module test modulefile command is used.
The subroutine should return 1 in case of success. If no value or any other value is returned, the test is considered failed ๐ญ (yes, only 1 counts, we don't make the rules)
๐ MODULEFILE DISPLAY ๐
The module display modulefile command will detail all changes that will be made to the environment ๐ After displaying all of the environment changes, modulecmd.tcl will call the ModulesDisplay subroutine.
And that ModulesDisplay subroutine is a great place to put additional descriptive information about the modulefile โ it's giving commentary track, it's giving director's cut ๐
๐ COMPATIBILITY WITH LMOD TCL MODULEFILE ๐
Okay so modulecmd.tcl can handle Tcl modulefiles or modulerc files written for Lmod โ yep, the alternative module implementation developed in Lua. Except for the specific cases listed below, those modulefiles can be evaluated by Modules without producing errors. Here are the key differences between the two implementations, bestie ๐ซถ
- The
remove-propertymodulefile command is evaluated as a no-operation command. No error pops up if this command is used in modulefiles, but literally no change happens either. ๐ - The
haveDynamicMPATHcommand is evaluated as a no-operation modulefile command. If a modulefile conditionally updates theMODULEPATHenvironment variable, this command is needed to help Lmod know that the modulefile changesMODULEPATH. Thespidersub-command on Modules does not need this information, because the modulefile is evaluated in the context of the current user to determine whetherMODULEPATHis updated. ๐ฆ - The
breakcommand does not accept any argument. A msg argument can be set on Lmod to provide a customized break error message. ๐ญ - The
setenv,unsetenv,prepend-path,append-path,remove-path,pushenvandmodule load,load-any,try-loadandunloadmodulefile commands do not support the--modeoption. An error is raised if this option is used. ๐จ - The
setenvandunsetenvmodulefile commands do not support the--respectoption. An error is raised if this option is used. ๐ - Use of
reportErroraborts modulefile evaluation on Lmod. On Modules, this command only reports an error message. ๐ - The
require-fullnamecommand only aborts load modulefile evaluation, whereas the Lmod implementation also aborts unload and display evaluations. ๐ - When processing a
familycommand, theLMOD_FAMILY_<NAME>environment variable is also defined, so it stays compatible with modulefiles or scripts relying on that variable. ๐ - When unloading a modulefile, the
pushenvcommand does not update the value of the environment variable if this modulefile was not defining the value currently in use. ๐ซถ - The third optional argument of
append-pathandprepend-pathcorresponds to a priority specification on Lmod, whereas these two commands accept multiple path element arguments on Modules. โจ - The
prereqcommand is equivalent to theprereq-anycommand on Modules, whereas on Lmod it is equivalent to theprereq-allcommand. ๐ - If the
auto_handlingconfiguration option is disabled, the requirements defined with thedepends-onordepends-on-anycommands are not automatically loaded, and an error is raised if none of these requirements are found loaded. ๐ตโ๐ซ - If the
auto_handlingorconflict_unloadconfiguration options are disabled, the conflicts defined with thefamilycommand are not automatically unloaded, and an error is raised when trying to load a module defining a family already defined by a loaded module. ๐ฅ - On
module load-anysub-command and modulefile command, a modulefile evaluation error is not reported, andmodule load-anycontinues to the next modulefile instead of aborting the whole process. No attempt to load listed modulefiles is made if one of these modulefiles is found already loaded. ๐ซ - On
module try-loadmodulefile command, each modulefile specified is considered an optional pre-requirement. If it is loaded afterward and if theauto_handlingconfiguration option is enabled, the dependent module will get automatically reloaded. ๐ธ
๐ SHELL SUPPORT ๐
The modulecmd.tcl program that evaluates modulefiles supports a whole buffet of shells and languages: sh family shells (sh, bash, ksh and zsh), csh family shells (csh and tcsh), fish, cmd, pwsh, python, perl, ruby, tcl, cmake, r, and lisp. Iconic. ๐
Modulefiles produce environment changes when evaluated, like defining an environment variable. The modulecmd.tcl program outputs the corresponding code for the selected "shell". Thereafter this code is evaluated by the module alias or function to update the current environment. ๐ซถ
Depending on the "shell" kind, not all the environment changes that can be defined in modulefiles are supported. The support matrix below summarizes the changes supported by the shells supported by modulecmd.tcl. Iโm bullet-ifying the table so it survives terminal rendering, but every x and every blank is exactly where it was. no cap ๐
In this list, x means the table has an x in that column; blank means the table cell was empty.
shโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias):x; shell functions (set-function,unset-function):x; command completion (complete,uncomplete): blank;chdir:x; x-resource:x.bashโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias):x; shell functions (set-function,unset-function):x; command completion (complete,uncomplete):x;chdir:x; x-resource:x.kshโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias):x; shell functions (set-function,unset-function):x; command completion (complete,uncomplete): blank;chdir:x; x-resource:x.zshโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias):x; shell functions (set-function,unset-function):x; command completion (complete,uncomplete): blank;chdir:x; x-resource:x.cshโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias):x; shell functions (set-function,unset-function): blank; command completion (complete,uncomplete): blank;chdir:x; x-resource:x.tcshโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias):x; shell functions (set-function,unset-function): blank; command completion (complete,uncomplete):x;chdir:x; x-resource:x.fishโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias):x; shell functions (set-function,unset-function):x; command completion (complete,uncomplete):x;chdir:x; x-resource:x.cmdโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias):x; shell functions (set-function,unset-function): blank; command completion (complete,uncomplete): blank;chdir:x; x-resource: blank.pwshโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias):x; shell functions (set-function,unset-function):x; command completion (complete,uncomplete):x;chdir:x; x-resource: blank.pythonโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias): blank; shell functions (set-function,unset-function): blank; command completion (complete,uncomplete): blank;chdir:x; x-resource:x.perlโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias): blank; shell functions (set-function,unset-function): blank; command completion (complete,uncomplete): blank;chdir:x; x-resource:x.rubyโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias): blank; shell functions (set-function,unset-function): blank; command completion (complete,uncomplete): blank;chdir:x; x-resource:x.tclโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias): blank; shell functions (set-function,unset-function): blank; command completion (complete,uncomplete): blank;chdir:x; x-resource:x.cmakeโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias): blank; shell functions (set-function,unset-function): blank; command completion (complete,uncomplete): blank;chdir: blank; x-resource:x.rโ environment variables (setenv,unsetenv,pushenv,append-path,prepend-path,remove-path):x; shell alias (set-alias,unset-alias): blank; shell functions (set-function,unset-function): blank; command completion (complete,uncomplete): blank;chdir:x; x-resource:x.
Tiny note, bestie: lisp is in the supported shells/languages list above, but it is not a row in the table, so Iโm not inventing a row for it ๐๐ซถ
โโโโโโโโโโผโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโโโโโค
โ lisp โ x โ โ โ โ x โ x โ
โโโโโโโโโโดโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโดโโโโโโโโดโโโโโโโโโโโโโ
And that's the last row, bestie ๐
lisp is the final one, with x in the first, fifth and sixth columns and vibes-only (read: blanks) everywhere else. The table is closed, the box-drawing characters have done their job, we're free ๐
Ok so now the actual tea about source-sh โจ The source-sh command evaluates a shell script and produces the modulefile commands corresponding to the environment changes made by that script. Like, it watches the script do its thing and then writes down the receipts ๐
source-sh is able to evaluate sh, bash, ksh, zsh, csh, tcsh and fish shell scripts โ a whole friend group of shells, no cap ๐๐ซถ
source-sh produces environment changes corresponding to the kinds listed in the table above ๐ Based on the evaluated script, refer to the above table to know the environment changes that will be rendered for the shell specified to modulecmd.tcl program. So yeah โ script goes in, you check the table, you know what's coming out for that shell. Iykyk ๐ฅ
๐ธ ENVIRONMENT ๐ธ
See the ENVIRONMENT <#module-environment> section in the module <#module-1> man page. That's it, that's the whole section โ she's short and she knows it ๐
๐ฆ SEE ALSO ๐ฆ
envml<#envml-1>ml<#ml-1>module<#module-1>ref:modulecmd(1)Tcl(n)TclX(n)id(1)xrdb(1)exec(n)uname(1)domainname(1)tclvars(n)lsort(n)string(n)
Go read them, they're literally all right there ๐๐
๐ NOTES ๐
Tcl was developed by John Ousterhout at the University of California at Berkeley. Respect the icon โญ
TclX was developed by Karl Lehenbauer and Mark Diehkans. Two whole legends, we stan ๐ซถ
๐ Copyright ๐
1996-2026, Modules Contributors
Three decades of modules, bestie โ that's main character energy fr fr ๐
And that's a wrap on MODULEFILE(5)! ๐ This was version 5.7.0, dated 2026-09-21, and it's the MODULEFILE(5) page you just finished reading all thirteen parts of โ genuinely iconic of you ๐ Now go forth and slay your environment variables ๐ฆโจ๐
๐ฆ where this page comes from
- arch rolling: environment-modules 5.7.0-3 ยท GPL-2.0-or-later
- centos-stream 10: environment-modules 5.7.0-1.el10 ยท GPL-2.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms