Skip to main content

切换Spack环境变量

· 4 min read
one

Spack的环境变量、自动补全等都由Spack目录下的脚本设置。例如,为bash设置环境变量的命令为

$ export SPACK_ROOT=/path/to/spack
$ source $SPACK_ROOT/share/spack/setup-env.sh

当我们有多个Spack时,直接source其中一个Spack的环境配置脚本可能不会达到预期效果。比如,首先加载了集群的公共Spack,随后切换到自己的本地Spack,实际上仍有些环境是公共Spack设置的。此时我们需要清除一下旧的环境。

以下均以bash为例。

Spack的环境变量

Spack的环境配置脚本setup-env.sh实际上会如下修改用户的环境:

  • 修改变量SPACK_ROOT
  • 修改变量PATH,添加$SPACK_ROOT/bin,但该目录已存在时会跳过修改;
  • 定义函数_spack_shell_wrapper,是处理Spack命令的函数;
  • 定义函数spack,是给用户使用的。

如果以上环境都已被设置,再source另一个路径下的Spack,很可能只有SPACK_ROOT被修改。此时用户使用which spack等命令都只能找到旧的变量和函数。尤其是,如果PATH没有正确被修改,用户实际执行的可执行文件仍然来自于旧路径。

重置Spack的环境

切换Spack最干净的方法就是重新开shell,重新source配置脚本。如果一定要在当前shell切换Spack,可以手动删除旧的环境变量PATH和函数_spack_shell_wrapperspack。如果Spack版本差的不多,实际上只需要修改PATH就差不多能正常使用。

下面提供一个可以删除这些环境的脚本。该脚本的输入参数为Spack的setup-env.sh路径。

#   Script:
# reset-env.sh
# Usage:
# source ./reset-env.sh /path/to/setup-env.sh
#
#!/bin/bash

unset_spack_path() {
# Figure out Spack paths
local spack_script=$1
local spack_share_dir="$(cd "$(dirname $spack_script)" > /dev/null && pwd)"
local spack_prefix="$(cd "$(dirname $(dirname $spack_share_dir))" > /dev/null && pwd)"
local spack_bin="${spack_prefix%/}/bin"

# Remove the specified directory from PATH
local path_old=$PATH
local path_canonical=":$path_old:"

if [[ "$path_canonical" =~ ":$spack_bin:" ]];
then
# Remove the given directory
local path_new="${spack_bin}${path_canonical//:$spack_bin:/:}"

# Remove the tail colon
path_new=${path_new%:}

# Export PATH, this will change the user environment
export PATH=$path_new

echo "removed from PATH: $spack_bin"
else
echo "removed nothing"
fi
}

unset_spack_func() {
# Spack functions
local spack_functions=(spack _spack_shell_wrapper)

for i in "${spack_functions[@]}"
do
if [ -n $i ] && [ "$(type -t $i)" = function ]
then
# This is supposed to change the user environment
unset -f $i
echo "unset function: $i"
else
echo "$i not found"
fi
done
}

echo -e "\nRemoving Spack directory from PATH..."
unset_spack_path "$1"

echo -e "\nUnsetting Spack functions..."
unset_spack_func

echo -e "\nSourcing ${1}..."
source "$1" &> /dev/null
if [ $? != 0 ]; then
echo "failed to source $1"
fi

echo -e "\nNow, you can run following commands for checking"
echo -e "\t$ which spack"
echo -e "\t$ env | grep -i spack"

该脚本需要source,使用方式如下

export SPACK_ROOT=/path/to/new/spack
$ source ./reset-env.sh $SPACK_ROOT/share/spack/setup-env.sh

脚本中的unset_spack_path用于计算一些路径并修改用户的PATH,执行完后,用户提供的新Spack的路径会并加到PATH最前面。unset_spack_func用于清除旧的函数。