Fabric为什么看不到我的.bash_profile?

时间:2011-11-04 05:46:16

标签: bash fabric .bash-profile

在Fabric中,当我尝试使用我的.bash_profile文件中的任何别名或函数时,它们无法识别。例如,我的.bash_profile包含alias c='workon django-canada',因此当我在iTerm或终端中输入c时,会执行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 个答案:

答案 0 :(得分:21)

编辑 - 事实证明,这在Fabric 1.4.4中得到了修复。来自更改日志:

  

[Feature] #725:更新了local以允许覆盖使用哪个本地shell。感谢Mustafa Khattab。

所以原来的问题会像这样修复:

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

这是你的问题。 Popen默认为/bin/sh。如果您自己调用Popen构造函数,则可以指定不同的shell,但是您通过Fabric使用它。不幸的是,Fabric无法传递shell,例如/bin/bash

很抱歉,它不能为您提供解决方案,但它应该回答您的问题。

修改

以下是有问题的代码,直接从local文件中定义的fabric 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子进程模块,shell = True激活。如果您需要执行任何特殊操作,请考虑直接使用子进程模块。

答案 1 :(得分:4)

一种解决方法是简单地包装bash命令周围的任何命令:

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

如果您需要执行大量操作,请考虑创建custom context manager

答案 2 :(得分:0)

看起来你正试图在本地使用virtualenvwrapper。您需要使本地命令字符串如下所示:

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

以下是您的真实that does that for you in a context manager示例。