如何在Python Fabric的`fabfile.py`中正确设置`env.hosts`?

9 投票
5 回答
8654 浏览
提问于 2025-04-17 12:00

当我运行这个 fabfile.py 文件时...

from fabric.api import env, run, local, cd

def setenv(foo):
  env.hosts = ['myhost']

def mycmd(foo):
  setenv(foo)
  print(env.hosts)
  run('ls')

用这个命令 fab mycmd:bar。我得到了这个输出...

['myhost']
No hosts found. Please specify (single) host string for connection:

这是什么情况?我搞不懂!我已经设置了 env.hosts,而且在 mycmd 函数里面看起来是有效的,但不知为什么那个 run 命令却不知道我指定的 hosts

我真是搞糊涂了。任何帮助都非常感谢!

5 个回答

3

你有没有试过使用hosts这个装饰器呢?

from fabric.api import env, run, hosts

@hosts('myhost')
def mycmd(foo):
    print(env.hosts)
    run('ls')
5

你现在的做法不是我通常使用Fabric的方式。

from fabric.api import *

def hostname():

    env.hosts = ['myhosts']

def mycmd():
    print env.hosts
    run('ls -l')

要运行这个,我会这样做:

fab hostname mycmd

这样可以让你选择想要在哪个主机上执行这个命令。

希望这能帮到你。

7

@Chris,你看到这种情况的原因是因为主机列表是在任务函数被调用之前就已经构建好了。所以,即使你在函数内部修改了 env.hosts,也为时已晚,无法产生任何影响。

而命令 fab setenv:foo mycmd:bar 的结果是你所期待的:

$ fab setenv:foo mycmd:bar
[myhost] Executing task 'mycmd'
['myhost']
[myhost] run: ls

这和被接受的答案是一样的,但由于 setenv 的定义方式,需要一个参数。

另一个例子:

from fabric.api import env, run, local, cd

env.hosts = ['other_host']

def setenv(foo):
    env.hosts = ['myhost']

def mycmd(foo):
    setenv(foo)
    print('env.hosts inside mycmd: %s' % env.hosts)
    run('ls')

这个的输出是:

$ fab mycmd:bar
[other_host] Executing task 'mycmd'
env.hosts inside mycmd: ['myhost']
[other_host] run: ls

Fatal error: Name lookup failed for other_host

Underlying exception:
    (8, 'nodename nor servname provided, or not known')
Aborting.

正如你所看到的,当 fabric 开始执行 mycmd 时,主机列表已经被设置为 ['other_host', ]

撰写回答