Подтвердить что ты не робот

Почему Fabric не видит мой .bash_profile?

В Fabric, когда я пытаюсь использовать любой псевдоним или функции из моего файла .bash_profile, они не распознаются. Например, my .bash_profile содержит alias c='workon django-canada', поэтому, когда я набираю c в iTerm или Terminal, выполняется workon django-canada.

My fabfile.py содержит

def test():
    local('c')

Но когда я пытаюсь fab test, это бросает это на меня:   [localhost] local: c

/bin/sh: c: command not found

Fatal error: local() encountered an error (return code 127) while executing 'c'

Aborting.

Другие функции Fabric работают нормально. Должен ли я указывать свой профиль bash где-то в ткани?

4b9b3361

Ответ 1

EDIT. Как оказалось, это было зафиксировано в Fabric 1.4.4. Из журнала изменений:

[Feature] # 725: Обновлен локальный, чтобы разрешить переопределение локальной оболочки. Благодаря Мустафе Хаттабу.

Итак, исходный вопрос будет исправлен следующим образом:

def test():
    local('c', shell='/bin/bash')

Я оставил свой первоначальный ответ ниже, который относится только к версии Fabric < 1.4.4.


Поскольку локальный не использует bash. Вы можете четко видеть это на своем выходе

/bin/sh: c: command not found

См? Он использует /bin/sh вместо /bin/bash. Это связано с тем, что команда Fabric local ведет себя несколько иначе, чем run. Команда local по существу является оберткой класса subprocess.Popen python.

http://docs.python.org/library/subprocess.html#popen-constuctor

И вот ваша проблема. По умолчанию по умолчанию используется значение /bin/sh. Можно указать другую оболочку, если вы вызываете конструктор Popen самостоятельно, но вы используете его через Fabric. И, к сожалению, для вас, Fabric не дает вам никаких средств для прохождения в оболочке, например /bin/bash.

Извините, что не предлагает вам решение, но оно должно ответить на ваш вопрос.

ИЗМЕНИТЬ

Вот этот код, вытащенный непосредственно из функции local, определенной в файле operations.py:

p = subprocess.Popen(cmd_arg, shell=True, stdout=out_stream,
    stderr=err_stream)
(stdout, stderr) = p.communicate()

Как вы можете видеть, он НЕ передает ничего для исполняемого ключевого слова. Это заставляет его использовать значение по умолчанию, которое равно /bin/sh. Если он использовал bash, он выглядел бы так:

p = subprocess.Popen(cmd_arg, shell=True, stdout=out_stream,
    stderr=err_stream, executable="/bin/bash")
(stdout, stderr) = p.communicate()

Но это не так. Вот почему они говорят следующее в документации для локального:

local - это просто удобная оболочка вокруг использования встроенного модуля подпроцессов Python с включенной оболочкой = True. Если вам нужно сделать что-нибудь особенное, подумайте об использовании модуля подпроцесса напрямую.

Ответ 2

Один способ обхода - просто обернуть любую команду, которую вы используете в команде bash:

@task
def do_something_local():
    local("/bin/bash -l -c 'run my command'")

Если вам нужно сделать много из них, подумайте о создании настраиваемого контекстного менеджера.

Ответ 3

Похоже, вы пытаетесь использовать virtualenvwrapper локально. Вы должны будете сделать свою локальную командную строку следующим образом:

    local("/bin/bash -l -c 'workon django-canada && python manage.py runserver'")

Вот пример по-настоящему который делает это для вас в диспетчере контекстов.