Skip to main content

执行模型

如果你已经阅读了 概述和教程,你应该已经熟悉Fabric在基本情况下的操作(单个主机上的单个任务)。但是,在许多情况下,你会发现自己想要执行多个任务和/或多个主机。也许你想将一个大任务分成更小的可重用部分,或者抓取一组服务器,寻找要删除的旧用户。这样的场景需要关于何时以及如何执行任务的特定规则。

本文探讨了Fabric的执行模型,包括主要执行循环,如何定义主机列表,如何建立连接等。

执行策略

Fabric默认为单一的串行执行方法,但Fabric 1.3(见 并行执行)提供了另一种并行模式。此默认行为如下:

  • 将创建任务列表。目前这个列表只是给 fab 的参数,保持给定的顺序。

  • 对于每个任务,从各种源生成特定于任务的主机列表(有关详细信息,请参阅下面的 如何构建主机列表)。

  • 任务列表按顺序遍历,每个任务在其主机列表中每个主机运行一次。

  • 其主机列表中没有主机的任务被认为是仅本地的,并且将始终运行一次且仅运行一次。

因此,给定以下fabfile:

from fabric.api import run, env

env.hosts = ['host1', 'host2']

def taskA():
    run('ls')

def taskB():
    run('whoami')

和以下调用:

$ fab taskA taskB

您将看到Fabric执行以下操作:

  • taskAhost1 上执行

  • taskAhost2 上执行

  • taskBhost1 上执行

  • taskBhost2 上执行

虽然这种方法是简单的,它允许任务函数的直接组合,并且(不同于将多主机功能推向单个函数调用的工具)启用shell脚本式逻辑,其中您可以内省输出或返回代码一个给定的命令,并决定下一步做什么。

定义任务

有关什么构成Fabric任务以及如何组织它们的详细信息,请参阅 定义任务

定义主机列表

除非你使用Fabric作为一个简单的构建系统(这是可能的,但不是主要的用例)有任务不会做你没有能力指定远程主机执行它们。有很多方法可以这样做,范围从全局到每个任务,并且它可以根据需要混合和匹配。

主机

在这种情况下,主机指的是什么也称为“主机字符串”:Python字符串指定用户名,主机名和端口组合,以 username@hostname:port 的形式。可以省略用户和/或端口(以及相关联的 @:),并且将分别由执行用户的本地用户名和/或端口22填充。因此,admin@foo.com:222deploy@websitenameserver1 都可以是有效的主机字符串。

还支持IPv6地址符号,例如 ::1[::1]:1222user@2001:db8::1user@[2001:db8::1]:1222。方括号只用于将地址与端口号分隔开。如果没有使用端口号,则括号是可选的。此外,如果通过命令行参数指定主机字符串,则可能需要在某些shell中转义方括号。

注解

用户/主机名拆分发生在找到的最后一个 @。电子邮件地址用户名有效,将正确解析。

在执行期间,Fabric对给定的主机字符串进行规范化,然后将每个部分(用户名/主机名/端口)存储在环境字典中,以供其使用,以及在需要时引用任务。有关详细信息,请参阅 环境字典,env

角色

主机字符串映射到单个主机,但有时可以按组安排主机。也许你有一些Web服务器在负载均衡器后面,并希望更新所有这些服务器,或者想在“所有客户端服务器”上运行任务。角色提供了一种定义对应于主机字符串列表的字符串的方法,然后可以指定,而不是每次都写出整个列表。

此映射定义为字典,env.roledefs,必须通过fabfile修改才能使用。一个简单的例子:

from fabric.api import env

env.roledefs['webservers'] = ['www1', 'www2', 'www3']

由于 env.roledefs 在默认情况下自然是空的,因此您也可以选择重新分配它,而不必担心丢失任何信息(前提是您不加载其他修改它的fabf,当然):

from fabric.api import env

env.roledefs = {
    'web': ['www1', 'www2', 'www3'],
    'dns': ['ns1', 'ns2']
}

角色定义不一定只是主机的配置,它们还可以包含您选择的其他角色特定设置。这通过将角色定义为 hosts 密钥下的词典和主机字符串来实现:

from fabric.api import env

env.roledefs = {
    'web': {
        'hosts': ['www1', 'www2', 'www3'],
        'foo': 'bar'
    },
    'dns': {
        'hosts': ['ns1', 'ns2'],
        'foo': 'baz'
    }
}

除了list/iterable对象类型之外,env.roledefs 中的值(或dict类型定义中的 hosts 键的值)可以是可调用的,因此在查找任务时而不是在模块加载时将被调用。 (例如,您可以连接到远程服务器以获取角色定义,而不必担心在调用例如 fab --list 时导致fabfile加载时出现延迟。)

角色的使用在任何方面都不是必需的 - 这只是为了方便您使用常见的服务器分组。

在 0.9.2 版更改: 添加了将可调用项用作 roledefs 值的能力。

如何构建主机列表

有多种方式来指定主机列表(全局或每任务),并且通常这些方法彼此重叠而不是合并在一起(虽然这在将来的版本中可能改变)。每个这样的方法通常被分成两部分,一部分主机和角色。

全球,通过 env

设置主机或角色的最常用方法是修改环境字典(环境hostsroles)中的两个键值对。在构建每个任务的主机列表时,在运行时检查这些变量的值。

因此,它们可以在模块级设置,这将在导入fabfile时生效:

from fabric.api import env, run

env.hosts = ['host1', 'host2']

def mytask():
    run('ls /var/www')

这样的fabfile,简单地运行为 fab mytask,将在 host1 上运行 mytask,随后是 host2

由于检查了 each 任务的env变量,这意味着如果您有需要,您可以在一个任务中实际修改 env,它将影响所有后续任务:

from fabric.api import env, run

def set_hosts():
    env.hosts = ['host1', 'host2']

def mytask():
    run('ls /var/www')

当作为 fab set_hosts mytask 运行时,set_hosts 是一个“本地”任务 - 它自己的主机列表是空的 - 但 mytask 将再次运行在给定的两个主机上。

注解

这种技术过去常常是创建假“角色”的方式,但是现在角色已经完全实现就不那么必要了。然而,在某些情况下,它可能仍然有用。

env.hosts 一起是 env.roles (不要与 env.roledefs!混淆),如果给出,将被视为在 env.roledefs 中查找的角色名称的列表。

全局地,通过命令行

除了在模块级修改 env.hostsenv.rolesenv.exclude_hosts 之外,还可以通过将逗号分隔的字符串参数传递给命令行开关 --hosts/-H--roles/-R 来定义它们。:

$ fab -H host1,host2 mytask

这样的调用直接等同于 env.hosts = ['host1', 'host2'] - 参数解析器知道寻找这些参数,并且将在解析时修改 env

注解

使用这些开关仅设置单个主机或角色是可能的,实际上很常见。 Fabric简单地在给定字符串上调用 string.split(','),因此没有逗号的字符串变成单项列表。

重要的是要知道这些命令行开关被解释为 之前 您的fabfile被加载:任何重新分配到 env.hostsenv.roles 在您的fabfile将覆盖它们。

如果您希望将命令行主机与fabfile定义的主机非破坏性地合并,请确保您的fabfile使用 env.hosts.extend():

from fabric.api import env, run

env.hosts.extend(['host3', 'host4'])

def mytask():
    run('ls /var/www')

当这个fabfile作为 fab -H host1,host2 mytask 运行时,env.hosts 将在执行 mytask 时包含 ['host1', 'host2', 'host3', 'host4']

注解

env.hosts 只是一个Python列表对象 - 所以你可以使用 env.hosts.append() 或任何其他这样的方法,你想要的。

每任务,通过命令行

全局设置主机列表仅在您希望所有任务始终在相同的主机列表上运行时有效。这并不总是如此,因此Fabric提供了几种更细化的方法,并指定仅适用于单个任务的主机列表。第一个使用任务参数。

fab 选项和参数 中所述,可以通过特殊的命令行语法指定每任务参数。除了为你的任务函数命名实际的参数外,这可以用于设置 hosthostsroleroles “参数”,当构建主机列表时,由Fabric解释(并从传递给任务本身的参数中删除)。 )

注解

由于逗号已用于将任务参数彼此分隔,必须在 hostsroles 参数中使用分号来描述各个主机字符串或角色名称。此外,参数必须引用以防止您的shell解释分号。

拿下面的fabfile,这是我们一直使用的,但它没有定义任何主机信息:

from fabric.api import run

def mytask():
    run('ls /var/www')

要为 mytask 指定每个任务主机,请执行它:

$ fab mytask:hosts="host1;host2"

这将覆盖任何其他主机列表,并确保 mytask 始终只运行在这两个主机上。

每任务,通过装饰

如果给定的任务总是在预定的主机列表上运行,您可能希望在您的fabfile本身中指定它。这可以通过用 hostsroles 装饰器装饰任务函数来完成。这些装饰器采用可变参数列表,如此:

from fabric.api import hosts, run

@hosts('host1', 'host2')
def mytask():
    run('ls /var/www')

它们还将采用单个可迭代的参数,例如。:

my_hosts = ('host1', 'host2')
@hosts(my_hosts)
def mytask():
    # ...

当使用时,这些装饰器覆盖针对特定任务的主机列表的 env 的任何检查(尽管 env 不以任何方式被修改 - 它被简单地忽略。)因此,即使上述fabfile已经定义了 env.hosts 或者对 fab 的调用使用 --hosts/-Hmytask 仍然在 ['host1', 'host2'] 的主机列表上运行。

然而,装饰器主机列表做 覆盖每任务命令行参数,如上一节所述。

优先顺序

我们一直在指出,设置主机列表的方法胜过其他方法,就像我们一直。但是,为了使事情更清楚,以下是快速细分:

  • 每任务,命令行主机列表(fab mytask:host=host1)绝对覆盖一切。

  • 每任务,装饰器指定的主机列表(@hosts('host1'))覆盖 env 变量。

  • 在fabfile(env.hosts = ['host1'])中设置的全局指定的主机列表 can 会覆盖在命令行上设置的列表,但是只有当你不小心(或者希望他们)时。

  • 在命令行(--hosts=host1)上设置的全局指定的主机列表将初始化 env 变量,但就是这样。

这个逻辑可能在未来稍微改变以更一致(例如,--hosts 以某种方式优先于 env.hosts,其方式与命令行每任务列出trump in-code相同),但是仅在向后不兼容的版本中。

组合主机列表

如何构建主机列表 中提到的各种来源之间没有主体的“工会化”。如果 env.hosts 被设置为 ['host1', 'host2', 'host3'],并且每个功能(例如通过 hosts)主机列表被设置为仅 ['host2', 'host3'],则该功能将在 host1 上执行 ,因为每个任务的装饰器主机列表优先。

但是,对于每个给定的源,如果指定了两个角色 主机,则它们将被合并到一个主机列表中。举个例子,这两个装饰器都使用的fabfile:

from fabric.api import env, hosts, roles, run

env.roledefs = {'role1': ['b', 'c']}

@hosts('a', 'b')
@roles('role1')
def mytask():
    run('ls /var/www')

假设在执行 mytask 时没有给出命令行主机或角色,则该fabfile将在 ['a', 'b', 'c'] 的主机列表上调用 mytask - role1 的联合和 hosts 调用的内容。

主机列表重复数据删除

默认情况下,为了支持 组合主机列表,Fabric重复数据删除最终主机列表,所以任何给定的主机字符串只存在一次。但是,这会阻止在同一目标主机上多次显式/故意运行任务,这有时很有用。

要关闭重复数据删除,请将 env.dedupe_hosts 设置为 False

排除特定主机

有时,排除一个或多个特定宿主是有用的,例如,以覆盖从角色或自动生成的主机列表中拉入的几个坏的或另外不期望的主机。

注解

从Fabric 1.4开始,您可能希望使用 skip_bad_hosts,它会自动跳过任何无法访问的主机。

主机排除可以用 --exclude-hosts/-x 全局完成:

$ fab -R myrole -x host2,host5 mytask

如果 myrole 被定义为 ['host1', 'host2', ..., 'host15'],则上述调用将以 ['host1', 'host3', 'host4', 'host6', ..., 'host15'] 的有效主机列表运行。

注解

使用此选项不会修改 env.hosts - 它只会导致主执行循环跳过请求的主机。

可以通过使用额外的 exclude_hosts kwarg来为每个任务指定排除,该额外的 exclude_hosts kwarg类似于上述的 hostsroles 每任务kwarg实现,因为它从实际的任务调用中被剥离。此示例将具有与上面的全局排除相同的结果:

$ fab mytask:roles=myrole,exclude_hosts="host2;host5"

请注意,主机列表是以分号分隔的,就像 hosts per-task参数一样。

组合排除

主机排除列表与主机列表本身一样,不能在它们可以声明的不同“级别”上合并在一起。例如,全局 -x 选项不会影响使用装饰器或关键字参数设置的每任务主机列表,也不会影响将每个任务 exclude_hosts 关键字参数影响全局 -H 列表。

此规则有一个小的例外,即在检查通过 @hosts@roles 设置的主机列表时,应考虑CLI级别的关键字参数(mytask:exclude_hosts=x,y。因此,用作为 fab taskname:exclude_hosts=host2 执行的 @hosts('host1', 'host2') 装饰的任务函数将仅在 host1 上运行。

与主机列表合并一样,此功能目前受到限制(部分是为了保持实现简单),并且可以在将来的版本中扩展。

使用 execute 智能执行任务

1.3 新版功能.

大多数信息涉及通过 fab 执行的“顶级”任务,例如我们称为 fab taskA taskB 的第一个例子。然而,将这样的多任务调用包装到他们自己的“元”任务中常常是方便的。

在Fabric 1.3之前,这必须手工完成,如 图书馆使用 中所述。面料的设计避开了神奇的行为,所以简单的 calling 一个任务功能 考虑装饰器如 roles

Fabric 1.3中的新功能是 execute 助手函数,它将一个任务对象或名称作为其第一个参数。使用它与从命令行调用给定任务实际上相同:上面在 如何构建主机列表 中给出的所有规则都适用。 (executehostsroles 关键字参数类似于 CLI每任务参数,包括它们如何覆盖所有其他主机/角色设置方法。)

例如,这里有一个fabfile,它定义了用于部署Web应用程序的两个独立任务:

from fabric.api import run, roles

env.roledefs = {
    'db': ['db1', 'db2'],
    'web': ['web1', 'web2', 'web3'],
}

@roles('db')
def migrate():
    # Database stuff here.
    pass

@roles('web')
def update():
    # Code updates here.
    pass

在Fabric <= 1.2中,确保 migrate 在DB服务器上运行并且 update 在Web服务器上运行(缺少手动 env.host_string 操作)的唯一方法是将两个作为顶级任务:

$ fab migrate update

Fabric> = 1.3可以使用 execute 设置元任务。更新 import 行如此:

from fabric.api import run, roles, execute

并将其附加到文件的底部:

def deploy():
    execute(migrate)
    execute(update)

这就是它的全部; roles 装饰器将被如预期地执行,从而产生以下执行序列:

  • migratedb1

  • migratedb2

  • updateweb1

  • updateweb2

  • updateweb3

警告

这种技术工作原理,因为本身没有主机列表(包括全局主机列表设置)的任务只运行一次。如果在将要在多个主机上运行的“常规”任务中使用,对 execute 的调用也将运行多次,导致子任务调用的乘法数量 - 小心!

如果您希望您的 execute 呼叫仅被呼叫一次,您可以使用 runs_once 装饰器。

参见

executeruns_once

利用 execute 访问多主机结果

在非平凡结构运行中,尤其是并行结构,您可能希望在结束时收集一组每个主机的结果值。呈现汇总表,执行计算等。

不可能在Fabric的默认“天真”模式(一个依赖于Fabric代表你的主机列表循环),但使用 execute 这是很容易。简单地从调用实际的工作任务切换到调用使用 execute 来控制执行的“元”任务:

from fabric.api import task, execute, run, runs_once

@task
def workhorse():
    return run("get my infos")

@task
@runs_once
def go():
    results = execute(workhorse)
    print results

在上面,workhorse 可以做任何Fabric东西 - 它的字面上你的老“天真”的任务 - 除了它需要返回一些有用的东西。

go 是你的新入口点(被调用作为 fab go,或whatnot),它的工作是从 execute 调用采取 results 字典,并做任何你需要的。有关该返回值的结构的详细信息,请查看API文档。

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

Fabric的一个常见的中高级用例是在运行时参数化目标主机列表的查询(当使用 角色 不足时)。 execute 可以使这个非常简单,像这样:

from fabric.api import run, execute, task

# For example, code talking to an HTTP API, or a database, or ...
from mylib import external_datastore

# This is the actual algorithm involved. It does not care about host
# lists at all.
def do_work():
    run("something interesting on a host")

# This is the user-facing task invoked on the command line.
@task
def deploy(lookup_param):
    # This is the magic you don't get with @hosts or @roles.
    # Even lazy-loading roles require you to declare available roles
    # beforehand. Here, the sky is the limit.
    host_list = external_datastore.query(lookup_param)
    # Put this dynamically generated host list together with the work to be
    # done.
    execute(do_work, hosts=host_list)

例如,如果 external_datastore 是一个简单的“在数据库中查找主机标签”服务,并且您希望在标记为与应用程序堆栈相关的所有主机上运行任务,则可以调用上面的:

$ fab deploy:app

可是等等!数据库服务器上的数据迁移已失效。让我们在源代码库中修复我们的迁移代码,然后再次部署DB框:

$ fab deploy:db

这个用例看起来类似于Fabric的角色,但是具有更多的潜力,绝不局限于单个参数。根据需要定义任务,以您需要的任何方式查询外部数据存储 - 它只是Python。

替代方法

与上面类似,但是使用 fab 连续调用多个任务而不是显式 execute 调用的能力是在主机列表查找任务中改变 env.hosts,然后在同一会话中调用 do_work:

from fabric.api import run, task

from mylib import external_datastore

# Marked as a publicly visible task, but otherwise unchanged: still just
# "do the work, let somebody else worry about what hosts to run on".
@task
def do_work():
    run("something interesting on a host")

@task
def set_hosts(lookup_param):
    # Update env.hosts instead of calling execute()
    env.hosts = external_datastore.query(lookup_param)

然后调用这样:

$ fab set_hosts:app do_work

这种方法相对于前一种方法的一个好处是,您可以用任何其他“主力”任务替换 do_work:

$ fab set_hosts:db snapshot
$ fab set_hosts:cassandra,cluster2 repair_ring
$ fab set_hosts:redis,environ=prod status

故障处理

一旦构建了任务列表,Fabric将开始执行它们,如 执行策略 中所述,直到所有任务已在其所有主机列表上运行。但是,Fabric默认为“故障快速”行为模式:如果出现任何错误,例如远程程序返回非零返回值或fabfile的Python代码遇到异常,执行将立即停止。

这通常是所需的行为,但规则有很多例外,因此Fabric提供了一个布尔设置 env.warn_only。它默认为 False,意味着错误条件将导致程序立即中止。然而,如果在失败时将 env.warn_only 设置为 True,例如,settings 上下文管理器Fabric将发出警告消息,但继续执行。

要从结构任务发出故障错误信号,请使用 abortabort 发出一个错误,就像它已被Fabric检测到并遵循控制流的正常执行模型。

连接

fab 本身实际上没有与远程主机建立任何连接。相反,它只是确保对于其中一个主机上的任务的每次不同运行,env var env.host_string 设置为正确的值。想要利用Fabric作为库的用户可以手动实现类似的效果(虽然从Fabric 1.3开始,使用 execute 是首选和更强大的。)

env.host_string (顾名思义)是“当前”主机字符串,是Fabric在运行网络感知功能时用于确定要进行(或重新使用)的连接的字符串。像 runput 的操作在共享字典中使用 env.host_string 作为查找键,它将主机字符串映射到SSH连接对象。

注解

连接字典(当前位于 fabric.state.connections)充当缓存,如果可能,选择返回先前创建的连接,以节省一些开销,否则创建新的连接。

懒惰的连接

因为连接是由单个操作驱动的,Fabric将不会实际建立连接,直到有必要。例如,这个任务在与远程服务器交互之前进行一些本地内务处理:

from fabric.api import *

@hosts('host1')
def clean_and_upload():
    local('find assets/ -name "*.DS_Store" -exec rm '{}' \;')
    local('tar czf /tmp/assets.tgz assets/')
    put('/tmp/assets.tgz', '/tmp/assets.tgz')
    with cd('/var/www/myapp/'):
        run('tar xzf /tmp/assets.tgz')

发生了什么,连接方面,如下:

  1. 两个 local 呼叫将运行而不进行任何网络连接;

  2. put 要求连接缓存与 host1 的连接;

  3. 连接缓存无法找到该主机字符串的现有连接,因此创建一个新的SSH连接,将其返回到 put

  4. put 通过该连接上传文件;

  5. 最后,run 调用要求缓存与同一主机字符串的连接,并给予现有的缓存连接供自己使用。

从这里外推,您还可以看到,不使用任何网络传播操作的任务实际上不会启动任何连接(尽管它们仍然会对其主机列表中的每个主机运行一次)。

关闭连接

Fabric的连接缓存从不关闭连接本身 - 它留给这个由使用它。 fab 工具为您执行此记帐:它遍历所有打开的连接,并在退出之前关闭它们(不管任务是否失败)。

库用户需要确保他们在程序退出之前显式关闭所有打开的连接。这可以通过在脚本结尾处调用 disconnect_all 来实现。

注解

disconnect_all 将来可能会搬迁到更公开的地点;我们仍然致力于使布料的图书馆方面更加巩固和组织。

多个连接尝试和跳过坏主机

从Fabric 1.4,可以尝试连接到远程服务器之前中止与错误:结构将尝试连接 env.connection_attempts 时间之前放弃,每次超时 env.timeout 秒。 (这些目前默认为1尝试和10秒,以匹配以前的行为,但他们可以安全地更改为任何你需要的。)

此外,连接到服务器的全部失败不再是绝对的硬停止:将 env.skip_bad_hosts 设置为 True,并且在大多数情况下(通常是初始连接),Fabric将简单地警告并继续,而不是中止。

1.4 新版功能.

密码管理

Fabric在某些情况下维护您的登录和sudo密码的内存中密码缓存;当多个系统共享相同的密码 [1] 时,或者如果远程系统的 sudo 配置不执行其自己的高速缓存,这有助于避免繁琐的重入。

预填充密码缓存

第一层是简单的默认或后备密码值 env.password (也可以通过 --password--initial-password-prompt 在命令行中设置)。这个env var存储单个密码,如果主机特定缓存(见下文)没有当前 主机字符串 的条目,那么将尝试该密码(如果为非空)。

env.passwords (复数!)用作每用户/每主机缓存,存储每个唯一用户/主机/端口组合的最近输入的密码(注意,如果手动修改结构,则必须包括 所有三个值 - 请参阅上面的链接详情)。由于此缓存,与同一会话中的多个不同用户和/或主机的连接将仅需要每个用户和/或主机的单个密码输入。 (先前版本的Fabric仅使用单个默认密码缓存,因此每次先前输入的密码无效时都需要重新输入密码。)

自动填充/从用户输入更新

根据您的配置和会话将连接到的主机数量,您可能会发现设置上述env变量中的一个或两个是有用的。但是,Fabric将根据需要自动填充它们,而无需任何其他配置。

具体地,每次向用户呈现密码提示时,输入的值用于更新单个默认密码高速缓存和用于 env.host_string 的当前值的高速缓存值。

指定仅限 sudo 的密码

在某些情况下(例如涉及双因素身份验证或其他在登录时提交密码的情况不是所需或正确的情况),您可能希望仅缓存用于 sudo 的密码,而不是重复使用登录和 sudo 目的。

为此,您可以设置 env.sudo_password 或填充 env.sudo_passwords,其镜像 env.passwordenv.passwords (如上所述)。这些值将 只要 用于响应 sudo 密码提示,并且永远不会在连接时提交。

还有一个类似于 --password 命令行标志,命名为 --sudo-password,并像 --initial-password-prompt,存在 --initial-sudo-password-prompt

注解

当两种类型的密码都被填充时(例如,如果 env.password = "foo"env.sudo_password = "bar"),将使用 sudo 特定密码。

注解

由于向后兼容性问题,用户输入的 sudo 密码仍将被缓存到 env.password/env.passwordsenv.sudo_password/env.sudo_passwords 纯粹用于非交互使用。

[1]

我们强烈建议使用SSH 基于密钥的访问,而不是依赖同质密码设置,因为它显着更安全。

利用本机SSH配置文件

命令行SSH客户端(例如由 OpenSSH 提供的)使用通常被称为 ssh_config 的特定配置格式,并且将从平台特定位置 $HOME/.ssh/config (或者给予 --ssh-config-path/env.ssh_config_path 的任意路径)中的文件读取。 )此文件允许指定各种SSH选项,例如默认或每个主机的用户名,主机名别名以及切换其他设置(例如是否使用 代理转发)。

Fabric的SSH实现允许从实际的SSH配置文件(如果存在)加载这些选项的子集。默认情况下,此行为不启用(为了向后兼容),但可以通过将 env.use_ssh_config 设置为 True 在您的fabfile的顶部打开。

如果启用,以下SSH配置指令将由Fabric加载和荣誉:

  • UserPort 将用于在没有另外指定时以下列方式填充适当的连接参数:

    • 如果未设置相应的env vars,将使用全局指定的 User/Port 代替当前缺省值(分别为本地用户名和22)。

    • 但是,如果 env.user/env.port are 设置,它们覆盖全局 User/Port 值。

    • 主机字符串本身中的用户/端口值(例如 hostname:222)将覆盖所有内容,包括任何 ssh_config 值。

  • HostName 可用于替换给定的主机名,就像使用常规 ssh 一样。因此,指定 HostName example.comHost foo 条目将允许您给Fabric的主机名 'foo',并在连接时扩展到 'example.com'

  • IdentityFile 将扩展(不替换) env.key_filename

  • ForwardAgent 将以“OR”方式增加 env.forward_agent:如果任一被设置为正值,则将启用代理转发。

  • ProxyCommand 将触发对主机连接使用代理命令,与常规 ssh 一样。

    注解

    如果您想要做的是从网关退回SSH流量,您可能会发现 环境 是一种比使用 ProxyCommand 作为网关的典型 ssh gatewayhost nc %h %p 方法更高效的连接方法(也将满足更多Fabric-level设置)。

    注解

    如果您的SSH配置文件包含 ProxyCommand 指令 and,您已将 环境 设置为非 None 值,则 env.gateway 将优先,并且 ProxyCommand 将被忽略。

    如果有一个预先创建的SSH配置文件,理由说明你将更容易修改 env.gateway (例如通过 settings),而不是完全解决你的conf文件的内容。