Fabric在两台服务器分别执行不同命令的正确方式及相关疑问
在Fabric中按服务器分配执行命令的方案
首先直接给你结论:修改env的方式在Fabric 1.x中是完全可行的,而如果是Fabric 2.x及以上版本,虽然不再使用env对象,但也能实现「主机列表包含所有服务器,指定命令在对应机器执行」的需求,下面分版本给你详细说明:
Fabric 1.x 版本(基于env的实现)
你提到的思路完全走得通,具体可以这么做:
- 先把所有目标服务器加入全局的
env.hosts,比如:from fabric.api import env, run env.hosts = ['ServerA', 'ServerB'] - 执行
command1前,临时修改env.hosts只保留ServerA:# 切换到ServerA执行command1 env.hosts = ['ServerA'] run('command1 --param xxx') - 再切换到ServerB执行
command2:# 切换到ServerB执行command2 env.hosts = ['ServerB'] run('command2 --param yyy')
更优雅一点的方式是用**角色(roledefs)**来管理服务器,可读性更好:
from fabric.api import env, run, roles env.roledefs = { 'server_a': ['ServerA'], 'server_b': ['ServerB'] } @roles('server_a') def run_on_a(): run('command1 --param xxx') @roles('server_b') def run_on_b(): run('command2 --param yyy') # 然后在命令行执行:fab run_on_a run_on_b
这种方式不需要手动修改env.hosts,Fabric会自动根据角色分配目标服务器。
Fabric 2.x+ 版本(无env的实现)
Fabric 2.x重构了API,不再使用env全局对象,而是用Connection和Group来管理服务器,实现思路更直观:
- 直接创建对应服务器的连接对象,分别执行命令:
from fabric import Connection # 连接ServerA并执行command1 conn_a = Connection('ServerA') conn_a.run('command1 --param xxx') # 连接ServerB并执行command2 conn_b = Connection('ServerB') conn_b.run('command2 --param yyy') - 如果要把所有服务器放到一个集合里统一管理,也可以用
Group,然后通过判断主机名来分配命令:from fabric import Group servers = Group('ServerA', 'ServerB') for conn in servers: if conn.host == 'ServerA': conn.run('command1 --param xxx') elif conn.host == 'ServerB': conn.run('command2 --param yyy')
对你问题的总结
- 修改
env的方式(Fabric 1.x)是正确可行的,只要在执行每个命令前切换env.hosts或env.roles,就能指定run的目标服务器。 - 可以在主机列表中包含所有服务器,不管是1.x还是2.x版本,都能通过临时切换目标、角色判断或主机名判断的方式,让对应命令在指定机器上执行。
不过要注意:Fabric 1.x已经停止维护了,如果是新项目,更建议用2.x+版本的API,代码结构更清晰,也更符合现代Python的编程习惯。
内容的提问来源于stack exchange,提问作者Saher Ahwal
相关产品推荐
相关产品推荐

