【问题标题】:How can I properly set the `env.hosts` in a function in my Python Fabric `fabfile.py`?如何在 Python Fabric `fabfile.py` 的函数中正确设置 `env.hosts`?
【发布时间】:2012-01-31 06:30:19
【问题描述】:

当我运行这个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

让我感到困惑。任何帮助将不胜感激!

【问题讨论】:

  • This 看起来是同一个问题,但答案更多。

标签: python deployment fabric


【解决方案1】:

@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', ]

【讨论】:

    【解决方案2】:

    你这样做的方式通常不是我使用 Fabric 的方式。

    from fabric.api import *
    
    def hostname():
    
        env.hosts = ['myhosts']
    
    def mycmd():
        print env.hosts
        run('ls -l')
    

    要运行它,我会这样做

    fab hostname mycmd

    这允许您分开要在哪些主机/主机上执行命令。

    希望对你有帮助。

    【讨论】:

    • 我将其标记为正确,因为我认为这种方法是“正确”的方法,但我仍然不明白我最初示例中的代码到底发生了什么.
    【解决方案3】:

    您是否尝试过使用 hosts 装饰器?

    from fabric.api import env, run, hosts
    
    @hosts('myhost')
    def mycmd(foo):
        print(env.hosts)
        run('ls')
    

    【讨论】:

      【解决方案4】:

      我知道这个问题已经很老了,但是以防万一有人偶然发现这个问题,我发现您不需要将其称为 fab 文件本身(您的文件不需要称为“fabfile .py”和命令不需要是fab setenv(foo) mycmd(bar)。由于您正在导入所需的fab元素,您可以调用任何您想要的文件(让我们称之为“testfile.py”)并简单地使用执行函数文件。这将使你的命令python testfile.py

      在测试文件中,像往常一样设置所有内容,但使用 execute 关键字启动函数。您的文件将如下所示:

      from fabric.api import env, run
      
      def setenv(foo):
          env.hosts = ['myhost']
          execute(mycmd, bar)
      
      def mycmd(bar):
          run('ls')
      
      setenv(foo)
      

      ** 请务必注意,执行命令确实看起来像一个常规函数调用。它将调用该函数并在一个逗号分隔的行中发送参数。您可以找到更多信息here

      所以你会启动你的程序,它首先会调用 setenv,然后 setenv 会执行 mycmd 函数。这样,您还可以在同一阵列中设置多个主机。比如:

      env.hosts=['myhost1','myhost2','myhost3']
      

      【讨论】:

        【解决方案5】:

        我已经想出了如何让它发挥作用:

        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')
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-08
          • 2020-09-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多