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

发布于 2024-12-14 04:12:41 字数 574 浏览 0 评论 0原文

在 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 功能工作正常。我是否必须在 Fabric 中的某个位置指定我的 bash 配置文件?

In Fabric, when I try to use any alias' or functions from my .bash_profile file, they are not recognized. For instance my .bash_profile contains alias c='workon django-canada', so when I type c in iTerm or Terminal, workon django-canada is executed.

My fabfile.py contains

def test():
    local('c')

But when I try fab test it throws this at me:
[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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

看轻我的陪伴 2024-12-21 04:12:41

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

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

因此,原来的问题将这样解决:

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 构造函数,但您是通过 Fabric 使用它,则可以指定不同的 shell。不幸的是,Fabric 无法为您提供传递 shell 的方法,例如 /bin/bash

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

编辑

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

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)。如果您需要做一些特殊的事情,请考虑直接使用 subprocess 模块。

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

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

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.


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

/bin/sh: c: command not found

See? It's using /bin/sh instead of /bin/bash. This is because Fabric's local command behaves a little differently internally than run. The local command is essentially a wrapper around the subprocess.Popen python class.

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.

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 local function defined in the operations.py file:

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:

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.

鱼忆七猫命九 2024-12-21 04:12:41

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

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

如果您需要执行大量这些操作,请考虑创建一个 自定义上下文经理。

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

@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.

允世 2024-12-21 04:12:41

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

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

这是您的一个真正的示例它在上下文管理器中为您执行此操作< /a>.

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

    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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文