Home > Software engineering >  Modules not loading when executed via a script (Bash)
Modules not loading when executed via a script (Bash)

Time:10-31

I'm writing a bash script to perform some commands on files. In order to do that, I need to load the modules which contain these commands. Now I can do these from the command line just fine, but I wanted to implement a check in a script to see if those modules are loaded, and if they are not, to load them. Here is what I have done so far (I am just 3 days into learning bash, so excuse any newbie errors):

#A list with all the necessary modules
declare -a modules=("CDO/1.9.7-gompi-2019a" "ncview/2.1.7-gompi-2019a")

echo "Running script"
echo ""

#Check if modules are loaded. If not, load them
for mod in "${modules[@]}"
do
    module is-loaded $mod

    if [ $? = 1 ]
    then
        echo "Loading ${mod}"
        module load $mod
    else
        echo "${mod} is already loaded"
    fi
done

echo ""
echo "Finished running script"

It enters the if statement, meaning the module is not loaded, and then says "Loading CDO...", but when I try to use commands from this module, it does not work because the module just doesn't seem to be executed. But the "module is-loaded" executes just fine. What am I doing wrong?

[diyon@login2 scripts]$ ./script.sh
Running script

Loading CDO/1.9.7-gompi-2019a
Loading ncview/2.1.7-gompi-2019a

Finished running script
[diyon@login2 scripts]$ cdo
-bash: cdo: command not found

CodePudding user response:

The clue is in the full name: “Environment Modules”

These modules (not to be confused with kernel modules or any other modules), are a tool used to configure the current environment (for development environments, administrators etc.).

I had not heard of these until today. According to these slides they use module files containing a declarative environment description written in Tcl. When you load them, they are converted to shell syntax, and evaled in the current environment.

———————-

The reason your script did not work is that a shell script executes in a new process, and can not change the environment of its parent process - the shell you launched it from. You configured the environment of the script (where the module dependant commands would have worked), but that environment is gone when the script exits.

The solution is probably to configure your environment modules in a module file (man modulefile or https://linux.die.net/man/4/modulefile), or whatever is recommended by the “Modules” documentation.

Or, you can implement your script as a shell function. Shell functions execute in the current shell environment, so your modules will still be loaded at the end of it.

If you run type module, you can see that module itself is a shell function, which is why it’s able to modify the current environment.

If you append the following function to the file ~/.bashrc and restart the shell, you can run load_modules to execute it.

I think quoting (variables etc) is unnecessary in this situation, but I added it anyway.

load_modules ()
{
    # A list with all the necessary modules
    local -a modules=('CDO/1.9.7-gompi-2019a'
                      'ncview/2.1.7-gompi-2019a')
    local mod

    echo "Running function"
    echo

    # Check if modules are loaded. If not, load them
    for mod in "${modules[@]}"
    do
        if module is-loaded "$mod"
        then
            echo "$mod is already loaded"
        else
            echo "Loading $mod…"
            module load "$mod"
        fi
    done

    echo
    echo "Finished running the function"
}

CodePudding user response:

The module command, from the Environment Modules software update the current environment session.

As explained by @dan, when executed as ./script.sh, your script is run in a subshell that ends at the end of the script execution. So when run this way the script updates the shell environment of the subshell not the parent shell.

If you source your script in your current shell session with source script.sh you will perform the module load commands in the current shell (not in a subshell session) so you will end with the current shell environment updated.

  • Related