我正在处理各种需要特定编译器的项目。幸运的是,在我工作的机器上,我得到了一个命令module
,这使得交换编译器变得很容易,例如
module unload PrgEnv-intel
module load PrgEnv-cray
或者,
module swap PrgEnv-intel PrgEnv-cray
还有一个命令module list
,它列出了当前加载的所有模块。输出大致为
Currently loaded modules:
1) module_foo/v2.3
2) module_bar/1.1.8
...
17) PrgEnv-pgi/5.2.40
或者类似的东西。(编译器不一定列在第17位;它只是在列表中的某个位置。)
我的问题是:有多种可能性可以在给定的时间加载编译器。我想在每个项目的目录中写一个脚本,它接受module list
的输出,找到列表中以PrgEnv
开头的部分(例如,xxx编译器的PrgEnv-xxx
,无论当前加载的是哪一个),然后为需要cray编译器的项目执行命令module swap PrgEnv-xxx PrgEnv-cray
。
这里的重点是,除非我un加载当前加载的编译器,否则我无法加载cray编译器。我可以通过检查module list
的结果来访问这些信息,但我宁愿只编写一个自动化所有这些的脚本。
这是疯狂的过度杀戮吗?也许吧,但我目前也在尝试学习如何使用UNIX命令解决更常见的问题,我认为这将是一次很好的学习经历。
#!/bin/bash
[ $# = 1 ] || { echo "Usage: $0 PrgEnv-new" >&2; exit 1; }
new_module="${1:?}"
cur_module=$(module list | sed -n '/^[0-9]*) *(PrgEnv-[a-zA-Z0-9_]*)/.*/ s//1/p')
if [ -z "$cur_module" ]
then module load "$new_module"
else if [ "$cur_module" != "$new_module" ]
then module swap "$cur_module" "$new_module"
else echo "Current module is $cur_module; so is requested module"
fi
它使用标准的(史前的)sed
符号,并且应该适用于任何版本。-n
抑制正常的"回声"操作。该模式查找后面跟有)
和空格的数字和PrgEnv-
,以及后面跟着/
和垃圾的标识符。它将所有这些替换为PrgEnv-
和标识符,并打印生成的行。它可以,也许应该,在那之后退出(将p
更改为{ p; q; }
)。
以下代码测试是否加载了模块。如果没有,则加载新的。如果新模块与当前模块不同,则会交换它们。如果新模块与当前模块相同,它会这么说
第一行检查是否使用一个参数调用了脚本,如果没有,则打印使用消息。第二个捕获参数中的值,检查它是否为空(所以有人没有想到会调用switch_env ''
,假设脚本名为switch_env
)。
module list | cut -d' ' -f2 | cut -d/ -f1 | grep ^PrgEnv | xargs module unload && module load PrgEnv-cray