Apple Mavericks - 为什么这个单行 BASH 脚本不能像我预期的那样设置我的 Python 虚拟环境?

Apple Mavericks - 为什么这个单行 BASH 脚本不能像我预期的那样设置我的 Python 虚拟环境?

我有以下 Bash 脚本:

#!/bin/bash
echo $MYPROJECT_HOME/bin/myproject_venv/bin/activate
source $MYPROJECT_HOME/bin/myproject_venv/bin/activate
echo $MYPROJECT_HOME/bin/myproject_venv/bin/activate

权限显示该文件是可执行的,并且归我所有。权限如下:

-rwxr-xr-x

当我在命令行运行脚本时,它两次打印出正确的脚本路径,activate正如我所料。但是,它无法正确运行中间的行 - 即脚本的来源行。

但是,如果我复制中间那行并在命令行运行它,它就能正常工作。

是什么赋予了?

答案1

问题

它运行正常(您可以通过echo向源文件添加命令来检查这一点),问题是它在不同的 shell 中运行。当您运行 shell 脚本时(使用 bash 作为示例,但同样的想法也适用于其他 shell),它会启动一个非登录、非交互式 shell 来运行。这意味着会启动一个单独的迷你实例,bash并且 bash是脚本的来源。这就是您设置的变量不存在于父 shell 中的原因。

你可以很容易地测试这一点:

$ cat test.sh
#!/bin/bash
export FOO="bar"
echo "FOO in test.sh is : $FOO"

$ export FOO="OOF"
$ echo $FOO
OOF                       ### Here, in the parent shell, $FOO is 'OOF'
$ ./test.sh
FOO in test.sh is : bar   ### In the shell running the script, $FOO is 'bar'
$ echo $FOO
OOF                       ### Back in the parent shell, $FOO is still 'OOF'

因此,shell 脚本在其自己的、单独的 shell 中运行,如下所述help source

source: source filename [arguments]
    Execute commands from a file in the current shell.

因此,source只会影响当前的shell,对于 bash 脚本来说,是启动来运行脚本本身的 shell,而不是您输入脚本名称的父 shell。


解决方案

如果您想要获取设置变量的文件,您应该从您正在运行的 shell 中执行此操作,只需source直接运行命令即可。

或者,您可以source通过将其添加到启动文件中来让所有新的 shell 实例都发生这种情况bash。这.profile在 OSX 和.bashrc大多数其他情况下都是如此。因此,编辑您的$HOME/.profile文件并添加以下行:

source $MYPROJECT_HOME/bin/myproject_venv/bin/activate

现在,您打开的所有新终端都将获取该activate文件。或者,如果您希望能够按需执行此操作,请将脚本转换为函数。将这些行添加到您的.profile

activate(){
  echo "Sourcing $TEST/activate"
  source $TEST/activate
}

与脚本不同,函数不会启动新的 shell 实例,因此可以修改启动它们的 shell。现在您可以运行activate来获取$TEST/activate文件。

答案2

脚本是否activate正在运行,但通过设置环境变量来工作?如果是这样,这可能会给您带来问题。作为测试,我创建了两个脚本commandactivate。第一个类似于您的 Bash 脚本:

#!/bin/bash
echo $TEST/activate
source $TEST/activate
echo $TEST/activate

并且activate是一个简单的单行:

export TEST="Hello World!"

输出显示环境变量的更改未保留。以下是我用来运行此命令的命令和结果:

export TEST="/Users/me"
./command

这似乎改变了环境变量;这是输出:

/Users/me/activate
Hello World!/activate

但回到我的命令提示符,我可以看到 $TEST 的值与之前相同:

echo $TEST

输出如下:

/Users/me

也许这就是你的问题?

相关内容