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
Может это твоя проблема?