zoukankan      html  css  js  c++  java
  • python fabric的用法

    1. Fabric的任务运行规则
    根据Fabric Execution model的说明,fabric默认以串行方式运行tasks,具体而言:
    1)在fabfile及其import文件中定义的task对象依次被创建(只是创建对象,并未真正执行),任务之间保持其定义的先后顺序。
    2)对于每个task,生成将要运行该task的目标机器列表。
    3)fab执行tasks时,按任务被指定的顺序依次执行这些任务;针对每个任务,依次在其指定的目标机器运行且只运行一次。
    4)未指定目标机器的task被当作本地任务运行,且只会被运行一次。

    假设在fabfile.py中定义了如下tasks:

    from fabric.api import run, env

    env.hosts = ['host1', 'host2']

    def taskA():
    run('ls')

    def taskB():
    run('whoami')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    在终端运行fab –list时,我们会看到taskA和taskB两个任务,运行之:

    $ fab taskA taskB
    1
    结果示例如下:

    taskA executed on host1
    taskA executed on host2
    taskB executed on host1
    taskB executed on host2
    1
    2
    3
    4
    通过上面的实例,大家应该可以明白fabric默认的串行执行策略是怎么回事。

    Fabric还允许我们指定以并行方式(借助multiprocessing模块实现多个进程并行执行)在多台机器上并行地运行任务,甚至还可在同一个fabfile文件中指定某些task以并行方式运行,而某些task以默认的串行方式运行。具体地,可以借助@parallel或@serial指定任务的运行模式,还可以在命令行中通过-P参数指定任务是否要并性执行。示例如下:

    from fabric.api import *

    @parallel
    def runs_in_parallel():
    pass

    def runs_serially():
    pass
    1
    2
    3
    4
    5
    6
    7
    8
    当运行如下命令时:

    $ fab -H host1,host2,host3 runs_in_parallel runs_serially
    1
    执行结果示例如下:

    runs_in_parallel on host1, host2, and host3
    runs_serially on host1
    runs_serially on host2
    runs_serially on host3
    1
    2
    3
    4
    此外,还可以通过对@parallel传入pool_size参数来控制并行进程数以防并行进程太多把机器拖垮。

    2. 为task指定目标机器
    有多种方式可以指定任务的将要运行的目标机器,下面分别进行说明。
    1)通过env.hosts或env.roles进行全局指定
    Fabric的env模块中定义了一系列全局变量,可以将其理解为可以控制fabric行为的环境变量。其中env.hosts和env.roles可以用来全局指定task的目标机器列表,这两个“环境变量”的默认值都是空列表[]。

    env.hosts的元素是fabric约定的”host strings”,每个host strings由username@hostname:port三部分构成,其中username和port部分可以缺省。本篇笔记前面的第1个代码实例其实已经说明了如何用env.hosts全局地指定task的目标机器列表,这里不再赘述。

    env.roles则是在配置了env.roledefs的情况下才有用武之地。在很多时候,不同的机器有着不同的角色,如有些是接入层,有些是业务层,有些是数据存储层。env.roledefs可以用来组织这些机器列表以体现其角色,示例如下:

    from fabric.api import env

    env.roledefs = {
    'web': {
    'hosts': ['www1', 'www2', 'www3'],
    },
    'db': {
    'hosts': ['db1', 'db2'],
    }
    }

    @roles('web')
    def mytask():
    run('ls /var/www')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    上例通过env.roledefs配置了两个角色web和db,分别包含3台、2台机器,并借助@roles为mytask指定了目标机器列表。

    2)通过命令行进行全局指定

    $ fab -H host1,host2 mytask
    1
    需要注意的是,命令行通过-H参数指定的机器列表在fabfile脚本load前被解释,故如果fabfile中重新配置了env.hosts或env.roles,则命令行指定的机器列表会被覆盖。为了避免fabfile覆盖命令行参数,在fabfile中应该借助list.extend()指定env.hosts或env.roles,示例如下:

    from fabric.api import env, run

    env.hosts.extend(['host3', 'host4'])

    def mytask():
    run('ls /var/www')
    1
    2
    3
    4
    5
    6
    此时,当我们运行”fab -H host1,host2 mytask”时,env.hosts包含来自命令行和fabfile的4台机器。

    3)通过命令行为每个任务指定机器列表

    $ fab mytask:hosts="host1;host2"
    1
    上述方式会覆盖全局指定的机器列表,确保mytask只会在host1, host2上执行。

    4)借助装饰器@hosts为每个任务指定目标机器

    from fabric.api import hosts, run

    @hosts('host1', 'host2')
    def mytask():
    run('ls /var/www')
    1
    2
    3
    4
    5
    或者:

    my_hosts = ('host1', 'host2')
    @hosts(my_hosts)
    def mytask():
    # ...
    1
    2
    3
    4
    每个任务的@hosts装饰器指定的机器列表会覆盖全局目标机器列表,但不会覆盖通过命令行为该任务单独指定的目标机器列表。

    上述4种为task指定目标机器列表的方式之间的优先级规则总结如下:
    1) Per-task, command-line host lists (fab mytask:host=host1) override absolutely everything else.
    2) Per-task, decorator-specified host lists (@hosts(‘host1’)) override the env variables.
    3) Globally specified host lists set in the fabfile (env.hosts = [‘host1’]) can override such lists set on the command-line, but only if you’re not careful (or want them to.)
    4) Globally specified host lists set on the command-line (–hosts=host1) will initialize the env variables, but that’s it.

    截止目前,我们可以看到,fabric允许我们混合使用上面列出的几种目标机器指定方式,但是我们要明白混合的结果是否符合预期。

    此外,fabric默认会对通过不同来源出现多次的同一个目标机器做去重,当然,可以通过设置env.dedupe_hosts为False来关闭默认的去重策略。甚至还可以指定任务需要跳过的机器列表。具体细节可以参考Fabric Execution model的说明,这里不赘述。

    3. 任务执行时,目标机器的密码管理
    如果你亲自运行上面的示例代码,就会发现,每次在目标机器远程执行task时,fabric均会要求输入目标机器的登录名及密码。如果要在多台机器上执行task,那这些密码输入的过程可以自动化吗?

    答案是肯定的。实现方式有两种,下面分别进行说明。

    1)通过env.password或env.passwords配置目标机器的登录信息
    下面的示例说明了如何通过env.passwords配置多台机器的登录信息:

    #!/bin/env python
    #-*- encoding: utf-8 -*-

    from fabric.api import run, env, hosts

    ## 需要注意的是,这里的host strings必须由username@host:port三部分构成,缺一不可,否则运行时还是会要求输入密码
    env.passwords = {
    'slvher@10.123.11.209:22': 'xxx',
    'work@10.123.11.210:23': 'yyy',
    }

    @hosts('10.123.11.209', '10.123.11.210')
    def host_os_type():
    run('uname -a')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    由于通过env.passwords配置了目标机器的登录用户名/密码,所以,当我们在终端运行fab host_os_type时,会发现不用手动输入密码了,大大方便了脚本远程自动执行。

    但是,这种明文指定登录名/密码的方式存在安全性问题,所以,fabric还支持以ssh key认证的方式免密在远程机器执行任务。

    在具体实现上,需要事先在目标机器上生成ssh public key并配置在~/.ssh/config文件中,然后在定义任务的fabfile中将env.use_ssh_config设置为True来启用基于ssh public key方式的身份认证,以便实现免密码远程执行任务。
    ---------------------
    作者:slvher
    来源:CSDN
    原文:https://blog.csdn.net/slvher/article/details/50414675
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    当开发者产生一个伟大的想法之后应该做的10件事
    PUT 还是 POST ?
    Failed to issue method call: Unit mysqld.service failed to load: No such file or directory.
    使用 Protocol Buffers 代替 JSON 的五个原因
    Java 打印堆栈的几种方法
    Eclipse调试Java的10个技巧
    如何使用命令查看系统名称?
    Feed系统架构资料收集
    dcm4chee 修改默认(0002,0013) ImplementationVersionName
    【原创】分布式之数据库和缓存双写一致性方案解析
  • 原文地址:https://www.cnblogs.com/linwenbin/p/10617236.html
Copyright © 2011-2022 走看看