linux下的source命令

背景:在一个项目中,需要在shell脚本文件中激活虚拟环境,然后在指定的虚拟环境中执行python脚本。遇到了各种坑,主要有:conda命令找不到、conda activate命令找不到、Docker相关问题。文本主要记录source命令含义,以及解决在脚本中激活虚拟环境的问题。
 

source命令

  • 语法:source filename [arguments]
  • 返回值:退出状态码
  • 参数:传递给filename的参数
  • 功能:source是bash shell的内置命令,用于读取filename脚本文件中的命令,并在当前shell执行。由于filename的执行环境是在当前shell,因此常用source命令在配置文件改变后,重新执行配置文件,避免重新登录。
     

source filename 与sh filename的区别

sh 会新建一个子shell,并在子shell中读取执行filename中的命令。子shell会继承父shell的环境变量,但子shell中新生成的变量或者环境变化并不会传播到父shell中,如需将新变量导入到父shell中,需使用export命令。
 

source activate激活虚拟环境报错

当使用source activate env_name时,提示“bash: activate: No such file or directory”错误,表示bash在环境变量中找不到activate命令,此时需要设置conda路径到环境变量。解决方案:

export PATH="~/miniconda3/bin:$PATH"

source activate 与conda activate的区别

  • 重要的一点: source activate 可以在shell脚本开头处激活虚拟环境,而用conda activate则提示“CommandNotFoundError: Your shell has not been properly configured to use ‘conda activate’.”错误。这点很重要,因为经常需要在脚本中先激活特定的环境,然后在特定环境中执行python脚本。观察下列实例,假设test.sh的代码如下:

    #! /bin/bash
    source activate python3.6
    

linux下的source命令_第1张图片
命令 sh -c “source activate python3.6” 不会对当前shell环境产生影响,因为sh会开启一个子shell,然后在子shell中激活了环境python3.6,然后结束命令退出子shell。

命令 sh -c "conda activate python3.6" 相当于在shell脚本开始处,激活环境,但出现conda activate NotFoundError,该问题的解决办法见后面

命令source test2.sh不会报错,并且在当前shell中成功激活python3.6虚拟环境。

  • 在网上还发现两者的另外一个区别:“从conda 4.4.0起,conda activate和conda deactivate是激活和退出环境的首选命令。它们比以前conda版本的source activate和source deactivate命令要灵活得多。conda activate命令还具有以下优点:(1)在所有操作系统,shell和平台上都是通用的,以及(2)没有与其他软件包(如python virtualenv的激活脚本)的脚本发生路径冲突。”
     

source 与source activate的区别

这是个简单但容易混淆的点,本质上source命令还是上面提到的bash的内置source命令,而activate本质是在 ~/miniconda3/bin目录下的一个可执行文件(同理deactivate也是位于同一位置的可执行文件)。activate后接的虚拟环境名称将作为参数输入到activate可执行文件中执行,源码如下所示:

linux下的source命令_第2张图片
 

shell脚本中激活conda虚拟环境

当在shell脚本中用conda activate激活虚拟环境时,会包如下错误:
linux下的source命令_第3张图片
查看conda init相关信息,发现在安装miniconda3时,会将下列信息自动写入~/.bashrc配置文件中,源码如下所示:
linux下的source命令_第4张图片
注意,打马赛克的地方是用户主目录地址,这个地方每个人不一样,后续用得上这段代码,将这段代码复制到需要调用虚拟环境的脚本最上面,然后激活虚拟环境。例如代码test3.sh所示:

#!/bin/sh
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('~/miniconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "~/miniconda3/etc/profile.d/conda.sh" ]; then
        . "~/miniconda3/etc/profile.d/conda.sh"
    else
        export PATH="~/miniconda3/bin:$PATH"
    fi
fi
unset __conda_setup
# <<< conda initialize <<<

# conda启动虚拟环境
conda activate python3.6

# 在指定的虚拟环境中启动特定脚本
python main.py

综合参考文献2、3, 当使用sh test3.sh命令时,会开启一个子shell,然后在子shell中激活python3.6虚拟环境,然后执行main.py(假设main.py依赖于python3.6环境),执行完毕后正常退出子shell,并进入当前shell环境。注意这种模式下当前环境是没有变化的,若需要当前环境也切换到python3.6,则使用source test3.sh
 

参考资料

【anaconda】激活环境失败

在Linux的shell脚本里激活conda 虚拟环境

用shell脚本激活conda虚拟环境

你可能感兴趣的:(#,Linux,操作系统,linux,shell,anaconda)