Skip to main content

常见问题(FAQ)

这些是我们从用户那里收到的一些最常遇到的问题或常见问题。它们不是替代阅读其余的文档,特别是 使用文档,所以请确保你检查这些,如果你的问题没有回答在这里。

Fabric安装但不运行!

在具有旧版本 setuptools 的系统上(特别是OS X Mavericks [10.9]以及旧的Linux发行版本),用户在运行Fabric的二进制脚本时经常遇到问题;这是因为这些 setuptools 太老了,无法处理现代分布格式Fabric和它的一些依赖关系可能使用。

我们用来重新创建此错误的一种方法:

  • OS X 10.9使用系统Python

  • Pip。 sudo easy_install pipsudo python get-pip.py

  • pip install fabric

  • fab [args] 然后导致以下跟踪:

    Traceback (most recent call last):
      File "/usr/local/bin/fab", line 5, in <module>
        from pkg_resources import load_entry_point
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources.py", line 2603, in <module>
        working_set.require(__requires__)
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources.py", line 666, in require
        needed = self.resolve(parse_requirements(requirements))
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources.py", line 565, in resolve
        raise DistributionNotFound(req)  # XXX put more info here
    pkg_resources.DistributionNotFound: paramiko>=1.10
    

最好的解决方案是获得一个更新的 setuptools (修复这个bug在许多其他),如此:

$ sudo pip install -U setuptools

卸载,然后重新安装Fabric,这样做后应该解决这个问题。

另一种方法是告诉 pip 不要使用 wheel 格式(确保您已经卸载Fabric和Paramiko):

$ sudo pip install fabric --no-use-wheel

最后,您还可以通过使用不同的Python解释器/生态系统(如 Homebrew特定的Python文档页)提供的)来获得成功。

如何动态设置主机列表?

使用 execute 和动态设置的主机列表

我的任务在所有主机上完成后,我如何运行?

利用 execute 访问多主机结果

Init脚本不工作!

Init样式的启动/停止/重新启动脚本(例如 /etc/init.d/apache2 start)有时不喜欢Fabric的虚拟分配,默认是活动的。在几乎所有情况下,使用 pty=False 显式调用有问题的命令都可以正常工作:

sudo("/etc/init.d/apache2 restart", pty=False)

如果您不需要交互式行为并频繁遇到此问题,您可能希望通过将 env.always_use_pty 设置为 False 来全局禁用pty分配。

我的(cd/workon/export/等等)调用似乎不工作!

虽然Fabric可以用于许多类似shell脚本的任务,但是有一些不直观的捕获:每个 runsudo 调用都有自己的不同的shell会话。这是必需的,以便Fabric在您的命令运行后可靠地找出其标准输出/错误和返回码。

不幸的是,它意味着像下面的代码不像你可能假设的行为:

def deploy():
    run("cd /path/to/application")
    run("./update.sh")

如果这是一个shell脚本,第二个 run 调用将使用 /path/to/application/ 的当前工作目录执行 - 但是因为这两个命令通过SSH在其自己的不同会话中运行,所以实际上尝试执行 $HOME/update.sh (因为您的远程主目录是默认工作目录)。

一个简单的解决方法是使用shell逻辑操作,例如 &&,它将多个表达式链接在一起(如果左侧执行没有错误),例如:

def deploy():
    run("cd /path/to/application && ./update.sh")

Fabric为这种特定的用例提供了一个方便的快捷方式,实际上是:cd。还有任意前缀命令的 prefix

注解

你也可能得到一个绝对路径和跳过目录改变完全:

def deploy():
    run("/path/to/application/update.sh")

但是,这要求所讨论的命令不假定您当前的工作目录!

如何使用 su 作为另一个用户运行命令?

这是 我的(cd/workon/export/等等)调用似乎不工作! 的一个特例。正如常见问题解释所解释的,像 su 这样的“有状态”命令在Fabric中不能正常工作,因此必须使用解决方法。

在以与登录用户不同的用户身份运行命令的情况下,您有两个选项:

  1. 使用 sudo 及其 user= kwarg,例如 sudo("command", user="otheruser")。如果你想从一系列命令中考虑 user 部分,请使用 settings 设置 env.sudo_user:

    with settings(sudo_user="otheruser"):
        sudo("command 1")
        sudo("command 2")
        ...
    
  2. 如果您的目标系统由于某种原因不能使用 sudo,您仍然可以使用 su,但是您需要通过告诉它运行一个特定的命令而不是打开一个shell,以非交互方式调用它。通常这是 -c 标志,例如。 su otheruser -c "command"

    要在同一个 su -c “包装器”中运行多个命令,您可以在 run 周围编写包装函数:

    def run_su(command, user="otheruser"):
        return run('su %s -c "%s"' % (user, command))
    

为什么我有时会看到 err: stdin: is not a tty

此消息通常由在远程用户的 .profile.bashrc 文件(或任何其他此类文件,包括系统范围的文件)中潜伏的程序(如 biffmesg)生成。Fabric的默认操作模式涉及在“登录模式”下执行Bash shell, ,这导致这些文件被执行。

因为Fabric还没有打扰到远程端的默认情况下(因为它通常不必要的)程序在您的启动文件中激发,期望tty存在,将抱怨,因此,stderr输出关于“stdin不是tty“或类似的。

有多种方法来处理这个问题:

  • 查找并删除或注释违规的程序调用。如果程序没有被有意添加,并且只是操作系统的遗留,这可能是安全的,并且是最简单的方法。

  • 覆盖 env.shell 以删除 -l 标志。这应该告诉Bash不加载你的启动文件。如果你不依赖于启动文件的内容(如别名或其他),这可能是一个很好的解决方案。

  • pty=True 传递给 runsudo,这将强制在远程端分配伪值,并且希望导致违规程序不那么容易。

为什么我不能在后台运行程序与 &?它使织物挂。

因为Fabric在每次调用 runsudo也可以看看)时在远程端执行一个shell,所以通过shell对后台进程将无法正常工作。后台进程仍然可能阻止调用shell退出,直到它们停止运行,这反过来防止Fabric继续其自己的执行。

修复这个的关键是确保您的进程的标准管道都与调用shell分离,这可以通过多种方式完成(按照鲁棒性顺序列出):

  • 如果现有程序存在,则使用预先存在的守护进程技术 - 例如,调用init脚本而不是直接调用服务器二进制。

    • 或者利用诸如 supervisordupstartsystemd 之类的进程管理器,这些工具允许您定义“运行”一个后台进程的意义,然后发出类似init-script的start/stop/restart/status命令。它们提供了许多优于传统init脚本的优点。

  • 使用 tmuxscreendtach 从运行shell完全分离进程;这些工具的好处是允许您在需要时重新连接到进程(尽管它们比 supervisord 类工具更具有特殊性)。

  • may 能够在 nohup 或类似的“in-shell”工具下的程序 - 但我们强烈建议以前的方法,因为 nohup 只为我们的少数用户工作得很好。

我的远程系统没有默认安装 bash,我需要安装 bash 吗?

虽然Fabric是考虑到 bash 编写的,但这不是绝对的要求。简单地改变 env.shell 来调用你想要的shell,并包含一个类似于 bash-c 参数的参数,这允许我们构建shell命令:

/bin/bash -l -c "<command string here>"

其中 /bin/bash -l -cenv.shell 的默认值。

注解

-l 参数指定一个登录shell,并且不是绝对必需的,只是在许多情况下方便。一些shell完全缺少选项,在这种情况下可以安全地省略。

一个相对安全的基线是调用 /bin/sh,它可以调用原来的 sh 二进制,或(在某些系统上) csh,并给它 -c 参数,像这样:

from fabric.api import env

env.shell = "/bin/sh -c"

这已被证明可以在FreeBSD上工作,也可以在其他系统上工作。

我使用 csh 远程和不断得到 Unmatched ". 的错误。

如果远程主机将 csh 用于您的登录shell,则Fabric需要设置shell变量 backslash_quote,否则任何报价转义Fabric不会工作。例如,将以下行添加到 ~/.cshrc:

set backslash_quote

有时我错误地要求输入密码而不是密码。

由于我们的SSH层中的某种错误,Fabric当前不可能始终准确地检测所需的身份验证类型。我们必须尝试猜测我们是否需要私钥密钥或远程服务器密码,在某些情况下,我们的猜测最终会出错。

最常见的这种情况是,您,本地用户,似乎有一个SSH钥匙扣代理运行,但远程服务器不能荣誉您的SSH密钥,例如。您尚未将公钥传输或使用不正确的用户名。在这种情况下,Fabric将提示您“请输入私钥的密码”,但您输入的文本实际上正在发送到远程端的密码身份验证。

我们希望在将来的版本中通过修改上述SSH库的一个分支来解决这个问题。

Fabric是线程安全的吗?

目前,不,它不是 - 当前版本的Fabric严重依赖共享状态,以保持代码库简单。但是,有明确的计划更新其内部,使Fabric可以是线程或其他并行化,所以您的任务可以并发运行在多个服务器上。