Вопрос 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
2017-11-25 17:34


происхождения




ответы:


Проблема

Он работает отлично (вы можете проверить это, добавив echo команда в исходный файл), проблема в том, что она запускается в другой оболочке. Когда вы запускаете сценарий оболочки (используя пример bash в качестве примера, но те же идеи применяются к другим оболочкам), он запускает не-login, неинтерактивную оболочку для запуска. Это означает, что отдельный мини-экземпляр 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 влияет только на текущий shell, который в случае скрипта 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 файл.


4
2017-11-25 23:32





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

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


2
2017-11-25 18:30



Да, я думаю, что это проблема, или она тесно связана с проблемой. Как я могу заставить скрипт bash иметь доступ к моим переменным окружения и иметь возможность писать им? Я думаю, что сценарий работает в какой-то новой / новой / другой среде, чем среда, в которой я нахожусь в командной строке. - jononomo
stackoverflow.com/questions/20201363/... - jononomo