我有以下 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
正在运行,但通过设置环境变量来工作?如果是这样,这可能会给您带来问题。作为测试,我创建了两个脚本command
和activate
。第一个类似于您的 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
也许这就是你的问题?