1

我正在编写一个 bash 脚本来对文件执行一些命令。为此,我需要加载包含这些命令的模块。现在我可以从命令行很好地执行这些操作,但我想在脚本中实现检查以查看是否加载了这些模块,如果没有加载它们。这是我到目前为止所做的(我刚刚学习 bash 3 天,所以请原谅任何新手错误):

#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"

它进入 if 语句,表示模块没有加载,然后说“正在加载 CDO...”,但是当我尝试使用来自该模块的命令时,它不起作用,因为模块似乎没有被执行. 但是“模块已加载”执行得很好。我究竟做错了什么?

[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
4

2 回答 2

1

线索全称:“Environment Modules”</p>

这些模块(不要与内核模块或任何其他模块混淆)是用于配置当前环境(用于开发环境、管理员等)的工具。

直到今天我才听说这些。根据这些幻灯片,他们使用包含用 Tcl 编写的声明性环境描述的模块文件。当您加载它们时,它们会被转换为 shell 语法,并eval在当前环境中编辑。

————————-

您的脚本不起作用的原因是 shell 脚本在新进程中执行,并且无法更改其父进程的环境 - 您从中启动它的 shell。您配置了脚本的环境(依赖于模块的命令本来可以工作的地方),但是当脚本退出时,该环境就消失了。

解决方案可能是在模块文件(man modulefilehttps://linux.die.net/man/4/modulefile)或“模块”文档中推荐的任何内容中配置您的环境模块。

或者,您可以将脚本实现为shell 函数。Shell 函数在当前的 shell 环境中执行,所以你的模块仍然会在它结束时被加载。

如果你运行type module,你可以看到它module本身就是一个shell函数,这就是它能够修改当前环境的原因。

如果将以下函数附加到文件~/.bashrc并重新启动 shell,则可以运行load_modules来执行它。

我认为在这种情况下引用(变量等)是不必要的,但我还是添加了它。

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…&quot;
            module load "$mod"
        fi
    done

    echo
    echo "Finished running the function"
}
于 2021-10-29T05:02:14.037 回答
0

module来自Environment Modules软件的命令更新当前环境会话。

正如@dan 所解释的,当执行为 时./script.sh,您的脚本将在一个子shell 中运行,该子shell 在脚本执行结束时结束。因此,当以这种方式运行时,脚本会更新子 shell 的 shell 环境,而不是父 shell。

如果您在当前 shell 会话中获取脚本,source script.sh您将在当前 shell 中执行module load命令(而不是在子 shell 会话中),因此您将以更新的当前 shell 环境结束。

于 2021-10-31T08:27:17.897 回答