使用Python的Fabric库进行嵌套调用“execute”

9 投票
1 回答
4545 浏览
提问于 2025-04-17 10:35

Python的Fabric库可以让你在不使用fab工具的情况下,调用Fabric的功能,这主要是通过execute函数来实现的。不过,当你在一个函数里面调用另一个用execute函数启动的函数时,就会出现一个问题。此时,Fabric会失去外层execute的上下文,导致它无法记住之前的状态。例如:

env.roledefs = {
    'webservers': ['web1','web2'],
    'load_balancer': ['lb1']
}

@roles('webserver')
def deploy_code():
    #ship over tar.gz of code to unpack.
    ...
    execute(remove_webserver_from_load_balancer, sHost=env.host_string)
    ...
    #shutdown webserver, unpack files, and restart web server
    ...
    execute(add_webserver_to_load_balancer, sHost=env.host_string)

@roles('load_balancer')
def remove_webserver_from_load_balancer(sHost=None):
   ssh("remove_host %s" % sHost)

execute(deploy_code)

在第一次调用execute之后,Fabric完全失去了上下文,接下来的所有命令都会在deploy_code函数中以host_string='lb1'的方式执行,而不是'web1'我该如何让它记住这个状态呢?

我想出了一个解决办法,但我觉得在未来的版本中可能会出问题:

 with settings(**env):
     execute(remove_webserver_from_load_balancer, sHost=env.host_string)

这个方法实际上是保存了所有的状态,并在调用后恢复,但看起来像是对这个函数的意外使用。有没有更好的方法可以告诉Fabric它在一个嵌套的execute中,并使用一个设置堆栈或类似的方法来记住状态呢?

谢谢!

1 个回答

1

你使用fabric的方式不太对。你应该直接调用 fab deploy_code,而不是像运行Python那样去执行fabfile。我建议你先看看教程,这样能更好地理解如何组织你的fabfile。

不过,你可以点击这里了解如何使用 execute(),还有这里可以找到更多具体的信息。

你在角色定义上有个小错误,少了一个's',这可能导致你在第二个任务时没有正确的主机字符串。

不过,除了这个,你也可以在execute()命令中直接设置角色和主机。

撰写回答