当前位置:  开发笔记 > 编程语言 > 正文

如何在Fabric文件中设置目标主机

如何解决《如何在Fabric文件中设置目标主机》经验,为你挑选了8个好方法。

我想使用Fabric将我的Web应用程序代码部署到开发,登台和生产服务器.我的fabfile:

def deploy_2_dev():
  deploy('dev')

def deploy_2_staging():
  deploy('staging')

def deploy_2_prod():
  deploy('prod')

def deploy(server):
  print 'env.hosts:', env.hosts
  env.hosts = [server]
  print 'env.hosts:', env.hosts

样本输出:

host:folder user$ fab deploy_2_dev
env.hosts: []
env.hosts: ['dev']
No hosts found. Please specify (single) host string for connection:

当我创建Fabric文档中set_hosts()显示的任务时,env.hosts设置正确.但是,这不是一个可行的选择,也不是装饰者.在命令行上传递主机最终会导致调用fabfile的某种shell脚本,我宁愿让一个工具正常工作.

它在Fabric文档中说'env.hosts只是一个Python列表对象'.根据我的观察,这根本不是真的.

谁能解释一下这里发生了什么?如何设置要部署的主机?



1> 小智..:

我这样做是通过声明每个环境的实际功能.例如:

def test():
    env.user = 'testuser'
    env.hosts = ['test.server.com']

def prod():
    env.user = 'produser'
    env.hosts = ['prod.server.com']

def deploy():
    ...

使用上面的函数,我将键入以下内容以部署到我的测试环境:

fab test deploy

...以及以下部署到生产:

fab prod deploy

这样做的好处是可以在任何 fab函数之前使用test和函数,而不仅仅是部署.它非常有用.prod


由于结构中存在错误(http://code.fabfile.org/issues/show/138#change-1497),最好将用户包含在主机字符串中(如produser@prod.server.com),而不是设置env .用户.
不幸的是,它似乎不再起作用 - 如果没有已经定义的env.hosts,结构将不会运行任务,并且不会在没有被定义为任务的情况下运行`fab ABC`样式的函数.

2> thomie..:

使用roledefs

from fabric.api import env, run

env.roledefs = {
    'test': ['localhost'],
    'dev': ['user@dev.example.com'],
    'staging': ['user@staging.example.com'],
    'production': ['user@production.example.com']
} 

def deploy():
    run('echo test')

用-R选择角色:

$ fab -R test deploy
[localhost] Executing task 'deploy'
...


或者,如果任务始终在同一角色上运行,则可以在任务上使用@roles()装饰器.
听起来像roledef是比在单独的任务中定义它们更好的解决方案.

3> tobych..:

这是一个更简单的serverhorrors版本答案:

from fabric.api import settings

def mystuff():
    with settings(host_string='192.0.2.78'):
        run("hostname -f")


根据[文档](http://docs.fabfile.org/en/latest/api/core/context_managers.html#fabric.context_managers.settings),设置上下文管理器用于覆盖`env`变量,而不是用于设置他们最初.我认为使用[roledefs](http://docs.fabfile.org/en/latest/usage/execution.html#roles),正如thomie建议的那样,更适合定义stage,dev和test等主机.

4> GoldenBoy..:

我自己也坚持了下来,但终于弄明白了.您无法任务中设置env.hosts配置.每个任务执行N次,每个主机指定一次,因此该设置基本上在任务范围之外.

查看上面的代码,您可以简单地执行此操作:

@hosts('dev')
def deploy_dev():
    deploy()

@hosts('staging')
def deploy_staging():
    deploy()

def deploy():
    # do stuff...

这似乎会做你想要的.

或者,您可以在全局范围内编写一些自定义代码,手动解析参数,并在定义任务函数之前设置env.hosts.出于几个原因,这实际上就是我如何设置我的.



5> j-a..:

从fab 1.5开始,这是一种动态设置主机的文档化方法.

http://docs.fabfile.org/en/1.7/usage/execution.html#dynamic-hosts

引用来自下面的文档.

将execute与动态设置的主机列表一起使用

Fabric的常见中高级用例是在运行时参数化一个目标主机列表的查找(当使用Roles时不够).执行可以使这非常简单,如下所示:

from fabric.api import run, execute, task

# For example, code talking to an HTTP API, or a database, or ...
from mylib import external_datastore

# This is the actual algorithm involved. It does not care about host
# lists at all.
def do_work():
    run("something interesting on a host")

# This is the user-facing task invoked on the command line.
@task
def deploy(lookup_param):
    # This is the magic you don't get with @hosts or @roles.
    # Even lazy-loading roles require you to declare available roles
    # beforehand. Here, the sky is the limit.
    host_list = external_datastore.query(lookup_param)
    # Put this dynamically generated host list together with the work to be
    # done.
    execute(do_work, hosts=host_list)


+1.这里有很多非常好的答案.

6> pztrick..:

相反,一些其他的答案,它可以修改env任务中的环境变量.但是,这env仅用于使用该fabric.tasks.execute功能执行的后续任务.

from fabric.api import task, roles, run, env
from fabric.tasks import execute

# Not a task, plain old Python to dynamically retrieve list of hosts
def get_stressors():
    hosts = []
    # logic ...
    return hosts

@task
def stress_test():
    # 1) Dynamically generate hosts/roles
    stressors = get_stressors()
    env.roledefs['stressors'] = map(lambda x: x.public_ip, stressors)

    # 2) Wrap sub-tasks you want to execute on new env in execute(...)
    execute(stress)

    # 3) Note that sub-tasks not nested in execute(...) will use original env
    clean_up()

@roles('stressors')
def stress():
    # this function will see any changes to env, as it was wrapped in execute(..)
    run('echo "Running stress test..."')
    # ...

@task
def clean_up():
    # this task will NOT see any dynamic changes to env

如果不包含子任务execute(...),将使用模块级env设置或从fabCLI 传递的任何内容.



7> serverhorror..:

你需要设置host_string一个例子:

from fabric.context_managers import settings as _settings

def _get_hardware_node(virtualized):
    return "localhost"

def mystuff(virtualized):
    real_host = _get_hardware_node(virtualized)
    with _settings(
        host_string=real_host):
        run("echo I run on the host %s :: `hostname -f`" % (real_host, ))



8> Morgan..:

解释为什么它甚至是一个问题.命令fab正在利用结构库来运行主机列表上的任务.如果您尝试更改任务中的主机列表,那么在迭代它时,您实际上是在尝试更改列表.或者在没有定义主机的情况下,循环遍历一个空列表,其中从未执行将列表设置为循环的代码.

env.host_string的使用是解决此问题的唯一方法,因为它直接指定要连接的主机的功能.如果您想要执行多个主机,这会导致一些问题,即您将重新构建执行循环.

人们在运行时设置主机的最简单方法是将env作为一个独特的任务保持,设置所有主机字符串,用户等.然后他们运行部署任务.它看起来像这样:

fab production deploy

要么

fab staging deploy

升级和生产就像你给出的任务一样,但他们不会自己调用下一个任务.它有这样的工作的原因,是该任务已经完成,并打破循环(主机,在ENV的情况下无,但在这一点上是一个的循环),然后有遍历主机(现在由前面的任务定义)重新开始.

推荐阅读
黄晓敏3023
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有