注:该文编写是结合了 Fabric 官方文档中的 以及 parallel execution 这两个章节来写的
当我们需要批量管理不同功能的服务器的时候,为了让不同功能的服务器执行不同的命令,这时候就需要用到 Fabric 的 的 env.roledefs 这个功能,
角色管理主机字符串匹配单个主机,但是有时候根据主机分组是非常有用的。或许你有一组在负载均衡下的 Web 服务器,并且你想对它们做全部更新操作,或者是在所有的客户端服务器上运行一个任务。 Roles 提供了一种正确给主机字符串分组的字符串定义方式,能通过该字符串代替整个主机组。
这个映射被定义成字典的方式。 env.roledefs 为了被使用,必须在 fabfile 中被定义。下面是一个简单的例子:
from fabric.api import env env.roledefs['webservers'] = ['www1', 'www2', 'www3']因为 env.roledefs 默认是是空值。或许你需要选择重新分配值而不用为丢失任何信息而担心(当你在修改它的时候得保证你没有加载其他任何的 fabflies)。
from fabric.api import env env.roledefs = { 'web': ['www1', 'www2', 'www3'], 'dns': ['ns1', 'ns2'] }除了列表目标主机的类型之外,env.roledefs 的值是立即生效的。当在查找以及代替模块加载时间在运行的时候就被调用了(and will thus be called when looked up when tasks are run instead of at module load time)【注:求高手正确翻译】。(例如,你可以连接远程服务器取得角色定义,并且在被调用的时候不用担心在 fabfile 文件加载的时候引起延迟。比如: fab --list)。
使用 roles 没有任何其他要求 -- 它仅仅是在你有服务器分组需求的情况下能提供一种便利的方式。
个人实践并且在生产应用了的代码,修改后删减如下:
#!/usr/bin/Python env from fabric.api import env from fabric.api import run from fabric.api import roles from fabric.api import execute #from fabric.context_managers import execute #env.user = 'username' env.password = 'password' env.roledefs = { 'test1': ['host1', 'host2'], 'test2': ['host3', 'host4'] } @roles('test1') def get_version(): run('cat /etc/issue') @roles('test2') def get_host_name(): run('hostname') def execute_all(): execute(get_version) execute(get_host_name)当你想在 web1 组里面只执行一台服务器的时候,你可以使用 env.exclude_hosts或者是 -x这个命令行参数来排除
env.exclude_hosts=['host1']或
fab -R web1 -x host1,host5 get_version这样执行的时候就会把 host1 这台服务器给排除在外了。
并行执行Fabric 默认是串行执行的(更多细节请参考 )。这个部分描述了在多个主机上并行执行任务的选择。可以通过每个任务的装饰器或者是命令行的全局开关来处理。
注:该功能只在 1.3 以及以后版本有。
因为 Fabric 1.x 默认不是线程安全的(并且因为在一般情况下,任务功能之间不会相互影响)这个功能是通过 Python 的 multiprocessing 模块实现的。它为每一个任务以及主机组合创建了一个新的线程。随意的使用了滑动窗口来避免在同一时间运行太多线程。
例如,设想一个你想更新许多 Web 服务器应用程序代码的场景。一旦代码分发出去,立即重载 web 服务(当更新失败的时候,允许很容易的回滚),如下的 fabfile 能实现如上需求:
from fabric.api import * def update(): with cd("/srv/django/myapp"): run("git pull") def reload(): sudo("service apache2 reload")然后在3台 web 服务器上串行的执行,如下:
$ fab -H web1,web2,web3 update reload正常的情况下,没有使用并行执行, Fabric 会按照如下顺序执行:
update on web1
update on web2
update on web3
reload on web1
reload on web2
reload on web3
当使用并行执行的时候(通过查看 获取更多细节),变成了这样:
update on web1, web2, and web3
reload on web1, web2, and web3