[英]Modules not loading when executed via a script (Bash)
我正在编写一个 bash 脚本来对文件执行一些命令。 为此,我需要加载包含这些命令的模块。 现在我可以从命令行执行这些操作就好了,但是我想在脚本中执行检查以查看这些模块是否已加载,如果未加载,则加载它们。 这是我到目前为止所做的(我只有 3 天时间学习 bash,所以请原谅任何新手错误):
#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
线索在全名中:“Environment Modules”
这些模块(不要与内核模块或任何其他模块混淆)是用于配置当前环境(用于开发环境、管理员等)的工具。
直到今天我才听说过这些。 根据这些幻灯片,他们使用包含用 Tcl 编写的声明性环境描述的模块文件。 加载它们时,它们会转换为 shell 语法,并在当前环境中进行eval
。
—————————
您的脚本不起作用的原因是 shell 脚本在新进程中执行,并且无法更改其父进程的环境 - 您从中启动它的 shell。 您配置了脚本的环境(模块相关命令将在其中工作),但是当脚本退出时该环境消失了。
解决方案可能是在模块文件( man modulefile
或https://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…"
module load "$mod"
fi
done
echo
echo "Finished running the function"
}
来自Environment Modules软件的module
命令更新当前环境会话。
正如@dan 所解释的那样,当作为./script.sh
执行时,您的脚本在子shell 中运行,该子shell 在脚本执行结束时结束。 因此,当以这种方式运行时,脚本会更新子 shell 的 shell 环境而不是父 shell。
如果您在当前 shell 会话中使用source script.sh
脚本,您将在当前 shell(而不是在 subshell 会话中)执行module load
命令,因此您将以更新当前 shell 环境结束。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.