自动化Fabric

神马是Fabric

  • 一个让你通过命令行执行无参数Python函数的工具
  • 一个让通过ssh执行的shell命令更加容器、更符合Python的命令库
  • 自然而然地,大部分用户把这两件事结合着用,使用 Fabric 来写和执行 Python 函数或 task

安装

  • 建议安装pyenv使用python的虚拟环境

  • pip安装,必须是python2.7版本以上不然不支持

pip3 install fabric3  #安装python3以上版本
pip install fabric    #安装python3以下版本

fab常用参数

  • fab选项参数
    -l 显示定义好的任何函数列表
    -f 执行fab入口文件,默认入口文件为fabfile.py
    -g 指定网关
    -H 指定目标主机,多个主机使用,分隔
    -P 以异步并行方式运行多主机任务,默认为串行任务,也就是依次执行
    -u 指定主机用户名
    -P 执行主机密码
    案例: fab -p 密码 -H 主机1,主机2... '命令'
    
  • fab操作案例

(fabric) [fabric@MAILCCOD ~]$ fab -H [email protected]:22 -- "pwd"  #远程执行pwd命令
[[email protected]:22] Executing task ''
[[email protected]:22] run: pwd
[[email protected]:22] Login password for 'root': 
[[email protected]:22] out: /root
[[email protected]:22] out: 
Done.

编写fabfile文件

  • 全局属性的设置

    • env对象的作用定义了fabfile的全局设置,支持多个属性,包括目标主机、用户、密码、角色

    • env.hosts定义多个目标主机、用ip或者主机名的列表
      格式: env.hosts= ["192.168.127.1","192.168.127.2"]

    • env.user: 定义用户名
      格式: env.user = "root"

    • env.port: 定义端口
      格式: env.port = 22

    • env.password:定义密码
      格式:env.password = "1"

    • env.passwords: 定义多台主机的用户名、ip地址、端口、密码

    格式: env.passwords = {
    "[email protected]:22":"passwd",
    "[email protected]:22":"passwd",
    
    }
    
    • env.gatewayd定义网关
      格式:env.gateway = "192.168.127.1"

    • env.roledefs:定义角色分组

    格式: env.roledefs = {
    "web":["192.168.127.2","192.168.127.3"]
    "Mysql":["192.168.127.4","192.168.127.5"]
    }
    
单机操作
  • 编写fabfile文件
fabfile.py

#coding:utf8
from fabric.api import *  #导出api方法

env.hosts =  ["127.0.0.1"]   #声明定义host主机
env.user = "root"            #声明定义用户名
env.password = "ChannelSoft*ccod4.5"  #声明定义密码
env.port = 20001             #声明定义密码

@task  #使用装饰器
def show():     #编写show函数,远程运行linux命令
    run("ls /home")
    run("ps -ef|rep resin")

@task
def Mem():
    run("free -m")

@task
def run_all():  #执行所有任务
    execute(show)
    execute(Mem)

if __name__ == "__main__":   #使用Python直接执行
    execute(run_all)
    
  • 运行fabfile文件
    fab -f fabfile.py show 运行show任务
    fab -f fabfile.py -l 显示执行的任务
    ./fabfile.py #执行调用
多机操作
  • 多机操作
#!/usr/bin/python
#coding:utf8
from fabric.api import *
env.user = "root"
env.hosts = ["192.168.127.1","192.168.127.2"]
env.passwords = {
    "[email protected]:22":"qnsoft",
    "[email protected]:22":"qnsoft",
}

#roledefs是定义角色分组
env.roledefs = {
    "Web":["192.168.127.1"],
    "DB":["192.168.127.2"]
}


@task
def show():
    run("df -h")

@task
@roles("Web")   #使用角色
def Echo():
    run("ifconfig ")

@task
@roles("DB")
def run_all():
    execute(show)  #此命令是调用上面定义的函数
    run("ifconfig")

if __name__ == "__main__":
    execute(run_all)

  • 运行代码
[auto@mongodb1 fabric]$ fab -f Fabric1-0.py -l   #使用fab命令显示可执行的任务
Available commands:
    Echo
    run_all
    show
[auto@mongodb1 fabric]$ fab -f Fabric1-0.py Echo  #执行Echo任务

常用的fabric的API

  • local: 执行本地命令
    格式: local(本地命令)

  • lcd: 切换到本地目录
    格式: lcd(本地目录)

  • cd: 切换远程目录
    格式: cd(远程目录)

  • run: 执行远程命令
    格式: run(远程命令)

  • sudo: sudo方式执行远程命令
    格式: sudo(远程命令)

  • put: 上传本地文件到远程主机
    格式: put(本地文件,远程文件)

  • get:从远程主机下载文件到本地
    格式: get(远程文件,本地文件)

  • prompt: 获取用户输入信息
    格式: prompt("please input user password:")

  • confirm: 获得提示信息确认
    格式: confirm("continue[Y/N]?")

  • reboot: 重启远程主机
    格式: reboot()

  • @task: 函数修饰符,标注过的fab命令可见,非标注过的fab命令不可见

  • @runs_once: 函数修饰符,标识的函数只会执行一次,不受多台主机影响

颜色输出

  • from fabric.colors import * 导入颜色函数
  • fabric.colors.blue(text, bold=False)
  • fabric.colors.cyan(text, bold=False)
  • fabric.colors.green(text, bold=False)
  • fabric.colors.magenta(text, bold=False)
  • fabric.colors.red(text, bold=False)
  • fabric.colors.white(text, bold=False)
  • fabric.colors.yellow(text, bold=False)

文件上传下载校验

  • 源代码
upload_file.py
#!/usr/bin/python
#coding:utf8

from fabric.api import *
from fabric.contrib.console import   confirm
from fabric.colors import *   #导入颜色函数

env.user = "root"
env.hosts = ["192.168.127.26"]
env.passwords = {
    "[email protected]:22":"ChannelSoft*ccod4.5"
}

#roledefs是定义角色分组
env.roledefs = {
    "fps":["192.168.127.2"]
}


#定义文件上传任务
@task
def upload_file():
    with settings(warn_only=True):  #异常处理
        local("tar zcf FPS.tar.gz /home/auto/fabric/Fps.py")
        result = put("FPS.tar.gz","/root/FPS.tar.gz")
    if result.failed  and not confirm("continue[y/n]"):  #异常处理,如果上传失败是否继续
        abort("Put tar file Failed")

    #获取本地和上传远端文件的m5d值是否一致
    with settings(warn_only=True):
        local_file = local("md5sum FPS.tar.gz",capture=True).split(" ")[0]
        remote_file = run("md5sum /root/FPS.tar.gz").split(" ")[0]

    if local_file == remote_file:
        print(green("Yes upload  Acss , M5D Ok"))
    else:
        print(read("Upload file Failed MD5 NO !!!"))

#定义文件下载任务
@task
def download_file():
    with settings(warn_only=True):
        get("/root/FPS.tar.gz","FPS.tar.gz")
        local("tar -zxf FPS.tar.gz -C ./ && cat Fps.py ")


@task
def run_all():
    execute(upload_file)
    execute(download_file)


if __name__ == "__main__":
    execute(run_all)

并行执行

  • 如何运作
    默认情况下,fabric会默认顺序执行所有的任务,为了任务函数之间并不会产生交互,该功能实现是基于Python multiprocessing模块,它为每个主机和任务组合创建一个线程,同时提供一个可选的弹窗用于阻止创建过多的进程

  • 如何使用装饰器
    由于并行执行影响的最小单位是任务,所有功能的启动和禁用也是以任务为单位使用parallel或者serial装饰器,如下所示:

#!/usr/bin/python
#coding:utf8

from fabric.api import *

@parallel
def runs_in_parallel():
    pass

def runs_serially():
    pass

如果这样执行:
$ fab -H host1,host2,host3 runs_in_parallel runs_serially

将会按照这样的流程执行:
runs_in_parallel 运行在 host1、host2 和 host3 上
runs_serially 运行在 host1 上
runs_serially 运行在 host2 上
runs_serially 运行在 host3 上

  • 命令行操作
    你也可以使用命令行选项 -P 或者环境变量 env.parallel 强制所有任务并行执行。不过被装饰器 `~fabric.decorators.serial 封装的任务会忽略该设置,仍旧保持顺序执行。
    例如,下面的 fabfile 会产生和上面同样的执行顺序:
from fabric.api import *

def runs_in_parallel():
    pass

@serial
def runs_serially():
    pass

在这样调用时:
$ fab -H host1,host2,host3 -P runs_in_parallel runs_serially
和上面一样,runs_in_parallel 将会并行执行,runs_serially 顺序执行。

  • bubble大小
    主机列表很大时,用户的机器可能会因为并发运行了太多的 Fabric 进程而被压垮,因此,你可能会选择 moving bubble 方法来限制 Fabric 并发执行的活跃进程数。
    默认情况下没有使用 bubble 限制,所有主机都运行在并发池中。你可以在任务级别指定parallel 的关键字参数 pool_size 来覆盖该设置,或者使用选项 -z 全局设置。

例如同时在 5 个主机上运行:

from fabric.api import *

@parallel(pool_size=5)
def heavy_task():
    # lots of heavy local lifting or lots of IO here

或者不使用关键字参数 pool_size:
$ fab -P -z 5 heavy_task

  • 案例
并行执行
#!/usr/bin/python
#coding:utf8
from fabric.api import *
from Hosts import *

@task
@roles("Web")
@parallel(pool_size=5) #意思说最大线程是为5个
def File():
    with prefix("cd /home") :
        run("ls -htrl")
#类似执行 cd /home && ls ccodrunner 的linux命令


if __name__ == "__main__":
    execute(File)

上下文切换

-使用with语句的上下文管理器

#!/usr/bin/python
#coding:utf8
from fabric.api import *

env.hosts =  ["127.0.0.1"]   #声明定义host主机
env.user = "root"            #声明定义用户名

env.password = "qnsoft"  #声明定义密码
env.port = 10000             #声明定义密码


@task
def File():
    with prefix("cd /home") : #with上下文切换
        run("ls ccodrunner")
#类似执行 cd /home && ls ccodrunner 的linux命令


if __name__ == "__main__":
    execute(File)

你可能感兴趣的:(自动化Fabric)