Почему Fabric не видит мой .bash_profile? - PullRequest
13 голосов
/ 04 ноября 2011

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

Мой 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 где-нибудь в ткани?

Ответы [ 3 ]

21 голосов
/ 17 ноября 2011

РЕДАКТИРОВАТЬ - Как выяснилось, это было исправлено в Fabric 1.4.4.Из журнала изменений:

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

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

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

Я оставил свой оригинальный ответ ниже, который относится только к версии Fabric <1.4.4. </p>


Потому что local не использует 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

И вот ваша проблема.По умолчанию Popen /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:

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

4 голосов
/ 26 марта 2012

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

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

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

0 голосов
/ 23 августа 2013

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

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

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

...