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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8005348/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 01:01:43  来源:igfitidea点击:

Why doesn't Fabric see my .bash_profile?

bashfabric.bash-profile

提问by saul.shanabrook

In Fabric, when I try to use any alias' or functions from my .bash_profilefile, they are not recognized. For instance my .bash_profilecontains alias c='workon django-canada', so when I type cin iTerm or Terminal, workon django-canadais executed.

在 Fabric 中,当我尝试使用文件中的任何别名或函数时.bash_profile,它们无法识别。例如我的.bash_profilecontains alias c='workon django-canada',所以当我输入ciTerm 或 Terminal 时,会workon django-canada被执行。

My fabfile.pycontains

我的fabfile.py包含

def test():
    local('c')

But when I try fab testit throws this at me: [localhost] 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.

Other Fabric functions work fine. Do I have to specify my bash profile somewhere in fabric?

其他 Fabric 功能工作正常。我是否必须在结构中的某处指定我的 bash 配置文件?

回答by Eric Palakovich Carr

EDIT - As it turns out, this was fixed in Fabric 1.4.4. From the changelog:

编辑 - 事实证明,这已在 Fabric 1.4.4 中修复。从变更日志:

[Feature] #725: Updated local to allow override of which local shell is used. Thanks to Mustafa Khattab.

[功能] #725:更新本地以允许覆盖使用哪个本地外壳。感谢穆斯塔法哈塔布。

So the original question would be fixed like this:

所以原来的问题会这样解决:

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

I've left my original answer below, which only relates to Fabric version < 1.4.4.

我在下面留下了我的原始答案,它只与 Fabric 版本 < 1.4.4 有关。



Because local doesn't use bash. You can see it clearly in your output

因为本地不使用 bash。您可以在输出中清楚地看到它

/bin/sh: c: command not found

See? It's using /bin/shinstead of /bin/bash. This is because Fabric's localcommand behaves a little differently internally than run. The localcommand is essentially a wrapper around the subprocess.Popenpython class.

看?它正在使用/bin/sh而不是/bin/bash. 这是因为 Fabric 的local命令在内部的行为与run. 该local命令本质上是subprocess.PopenPython 类的包装器。

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

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

And here's your problem. Popen defaults to /bin/sh. It's possible to specify a different shell if you are calling the Popen constructor yourself, but you're using it through Fabric. And unfortunately for you, Fabric gives you no means to pass in a shell, like /bin/bash.

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

Sorry that doesn't offer you a solution, but it should answer your question.

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

EDIT

编辑

Here is the code in question, pulled directly from fabric's localfunction defined in the operations.pyfile:

这是有问题的代码,直接从文件中local定义的结构函数中提取operations.py

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

As you can see, it does NOT pass in anything for the executable keyword. This causes it to use the default, which is /bin/sh. If it used bash, it'd look like this:

如您所见,它不会为可执行关键字传递任何内容。这会导致它使用默认值,即 /bin/sh。如果它使用 bash,它看起来像这样:

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

But it doesn't. Which is why they say the following in the documentation for local:

但事实并非如此。这就是为什么他们在本地文档中说以下内容:

local is simply a convenience wrapper around the use of the builtin Python subprocess module with shell=True activated. If you need to do anything special, consider using the subprocess module directly.

local 只是围绕使用内置 Python 子进程模块并激活 shell=True 的便利包装器。如果您需要做任何特殊的事情,请考虑直接使用 subprocess 模块。

回答by ashwoods

One workaround is simply to wrap whatever command you have around a bash command:

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

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

If you need to do a lot of these, consider creating a custom context manager.

如果您需要做很多这些,请考虑创建自定义上下文管理器

回答by Dave

It looks like you're trying to use virtualenvwrapper locally. You'll need to make your local command string look like this:

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

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

Here's an example by yours truly that does that for you in a context manager.

这是你的一个例子,它在上下文管理器中为你做这件事