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 сценарий, как я ожидаю. Тем не менее, он неправильно запускает среднюю строку - ту, которая является источником сценария.

Однако, если я скопирую эту среднюю строку и запусту ее в командной строке, она будет работать нормально.

Что дает?

2 ответа

Решение

Проблема

Он работает отлично (вы можете проверить это, добавив echo в исходный файл), проблема в том, что он запускается в другой оболочке. Когда вы запускаете сценарий оболочки (используя bash в качестве примера, но те же идеи применимы и к другим оболочкам), он запускает неинтерактивную, неинтерактивную оболочку для запуска. Это означает, что отдельный мини-экземпляр bash запускается и что bash это тот, который источник вашего сценария. Вот почему переменные, которые вы устанавливаете, отсутствуют в родительской оболочке.

Вы можете проверить это достаточно легко:

$ 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'

Таким образом, сценарии оболочки запускаются в отдельной, отдельной оболочке и, как указано в help source:

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

Так, source Влияет только на текущую оболочку, которая в случае сценария bash запускается для запуска самого сценария, а не родительской оболочки, в которой вы вводили имя сценария.


Решения

Если вы хотите получить файл, который устанавливает переменные, вы должны сделать это из оболочки, в которой вы работаете, просто запустите source командовать напрямую.

В качестве альтернативы, вы могли бы иметь source произойдет для всех новых экземпляров оболочки, добавив его в ваш bash файл запуска. Это .profile в OSX и .bashrc в большинстве других случаев. Итак, отредактируйте ваш $HOME/.profile файл и добавьте эту строку:

source $MYPROJECT_HOME/bin/myproject_venv/bin/activate

Теперь все новые открытые терминалы будут получены activate файл. Или, если вы хотите сделать это по требованию, превратите ваш скрипт в функцию. Добавьте эти строки в свой .profile:

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

Функции, в отличие от скриптов, не запускают новый экземпляр оболочки и, следовательно, могут модифицировать оболочку, из которой вы их запускаете. Теперь вы можете запустить activate источник $TEST/activate файл.

Может быть, сценарий 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

Может это твоя проблема?

Другие вопросы по тегам