关于部署:如何在我的Python Fabric`fabfile.py`中的函数中正确设置`env.hosts`?

How can I properly set the `env.hosts` in a function in my Python Fabric `fabfile.py`?

当我运行这个fabfile.py时…

1
2
3
4
5
6
7
8
9
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。我得到这个输出…

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

什么,什么?!我不明白?我已经设置了env.hosts,它似乎在mycmd函数的"内部"是有效的,但由于某种原因,run命令不知道我指定的hosts

把我弄糊涂了。任何帮助都将不胜感激!


@Chris,您看到这种行为的原因是因为主机列表是在调用任务函数之前构建的。所以,即使您在函数内部更改了env.hosts,它也为时已晚,无法产生任何效果。

虽然命令fab setenv:foo mycmd:bar会导致您预期的结果:

1
2
3
4
$ fab setenv:foo mycmd:bar
[myhost] Executing task 'mycmd'
['myhost']
[myhost] run: ls

这与公认的答案相同,但由于setenv的定义方式,需要进行论证。

另一个例子:

1
2
3
4
5
6
7
8
9
10
11
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')

其结果是:

1
2
3
4
5
6
7
8
9
10
$ 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.

如您所见,当结构开始执行mycmd时,主机列表已经设置为['other_host', ]


你做这件事的方式通常不是我用布料的方式。

1
2
3
4
5
6
7
8
9
from fabric.api import *

def hostname():

    env.hosts = ['myhosts']

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

为了运行这个,我会这样做

fab hostname mycmd

这允许您分离要在哪个主机上执行命令。

希望有帮助。


你试过用主机装饰器吗?

1
2
3
4
5
6
from fabric.api import env, run, hosts

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

我已经知道如何让它工作:

1
2
3
4
5
6
7
8
9
10
from fabric.api import env, run, local, cd

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

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