wood, bob wrote:
> In our environment we have several tools (such as gcc) which may
> show up in more that one directory on the user's PATH. I was
> hoping to use prepend-path to make sure the correct directory
> shows up at the front of the PATH. But it appears that
> prepend-path doesn't do anything if the directory already exists
> somewhere in the PATH variable.
>
> Is there an easy way to force a directory to the front of a PATH
> even if it's already in the PATH elsewhere? I know I can just use
> setenv instead of prepend-path, but I was hoping to avoid
> duplication of directories.
>
> Example: Suppose PATH = /bin:/usr/bin:/usr/local/bin, and my
> module specifies
>
> prepend-path PATH /usr/local/bin
>
> I would like PATH to end up as /usr/local/bin:/bin:/usr/bin
Hello Bob,
I understand what you're trying to do here, but there's a
reason that modules is programmed to do this. If modules
adds a dir to a variable, it does so in a certain position
dictated by 1) the order in which the modulefiles were read
and 2) your choices about append-path and prepend-path in
those modulefiles. If you have the same path in more than
one of the modulefiles, then you have a problem that will
show up when you try to unload or switch one of them. The
path will be removed by the first modulefile to be unloaded
that has this path in it; this leave your environment in a
different state than you probably intended.
In other words, if you do this:
% module load A B
then later do
% module load C
where C has the same dir going into the same variable as A,
then you
% module unload C
you will no longer have the dir in the variable at all. This
breaks one of the features of modulefiles, which is that they
are normally atomic. A remove operation has no way to know
which of the duplicate vars to remove, as it does not know if
it was loaded before or after the other modulefile that has
the same dir in it.
Now with that said, if you're in between a rock and a hard
place and can't rework your modulefiles to achieve your goal,
I think you could use some Tcl to do a one-time change. What
I mean by "one-time" is that you will not be able to unload
the modulefile and get back to the same environment you had
before it was loaded as outlined above.
Something like:
set add_dir /usr/local/bin
if {![module-info mode remove] && ![module-info mode switch] &&
[is-loaded local]} {
puts stderr "Unloading local...\n"
module unload local
}
prepend-path PATH ${add_dir}
Note that the above code works only on the C version of modules
due to the use of "is-loaded" (at least in the version of
modulecmd.tcl that I have that command is not implemented).
You could use an env var to flag the presence of such a
module or try to process the LOADEDMODULES variable if you're
using the Tcl version, perhaps. My modulecmd.tcl is one of the
earlier versions from Mark Lakata that has a couple of edits
that allow it to work in our environment, but newer versions
may have the is-loaded command implemented.
If you don't know which modulefile might be loaded that also
added ${add_dir} as in this example, then I think you could
instead use the Tcl regexp command to remove the dir from the
env(PATH) string if it is found to already be in there prior to
issuing the prepend-path command. This ought to work on both
the C version and the Tcl version of modules.
Again, this is a one-time action; you'd need to reload your
environment from scratch to get back to a known state. I do
not recommend doing so for production work; I suspect you'll
end up spending far more time explaining to people why their
environment isn't what they expect when they unload/switch
modulefiles. I've definitely been there, done that.
Regards,
- Leo
|