fabric 官网英文文档:http://www.fabfile.org/
《Python自动化运维技术与最佳实践》
如何用 Fabric 实现无密码输入提示的远程自动部署:
fabric实现远程操作和部署:
简介
Fabric 是一个 Python 的库,同时它也是一个命令行工具。它提供了丰富的同 SSH 交互的接口,可以用来在本地或远程机器上自动化、流水化地执行 Shell 命令。使用 fabric 提供的命令行工具,可以很方便地执行应用部署和系统管理等操作。因此它非常适合用来做应用的远程部署及系统维护。其上手也极其简单,你需要的只是懂得基本的 Shell 命令。
fabric 依赖于 paramiko 进行 ssh 交互,fabric 的设计思路是通过几个 API 接口来完成所有的部署,因此 fabric 对系统管理操作进行了简单的封装,比如执行命令,上传文件,并行操作和异常处理等。
paramiko 是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,fabric 和 ansible 内部的远程管理就是使用的 paramiko 来现实。
fabric 简介 和 各个版本差异比较:http://www.mamicode.com/info-detail-2337088.html
1、Python 官网发布的地址
- Fabric1:https://pypi.org/project/Fabric/
- Fabric2:https://pypi.org/project/fabric2/
- Fabric3:https://pypi.org/project/Fabric3/
2、区别
- 1)Fabric1、Fabric和fabric2:Fabric 和 Fabric2 在 Pypi 中就是同一个东西,fabric2 只是 Fabric 的替代名称,为了便于使用备用名称进行安装。Fabric2 和之前的 Fabric1 相比,完全重写了,接口和功能都有很大改动,官网也不建议继续用 Fabric1,建议升级到 Fabric2。‘而最新版也早就支持 Python 3.4+、Python2.7 了。
- 2)Fabric3:Fabric3 是非官网的,是之前使用 Fabric 时,没有支持 Python3 的版本,有人fork 出来,加了 Python3 的支持,但现在应该已经不维护了。
3、总结
尽量使用最新的 Fabric2。
Fabric 在升级 2.x 之后,几乎就是重写了。很多以前的用法都变了,然后在 1.x 时代,本地和远程都是用一套代码处理,但是 2.x 的时候将 local 处理部分和远程处理部分分别拆分为 fab 和 invoke了,拆分的理由可以参考 这里。
忘记 1.x 的一切,然后从头开始
- http://docs.fabfile.org/en/2.3/getting-started.html
一、fabric2 模块使用
fabric2 是 python 的一个库,同时也是命令行工具,使用 fabric2 模块,可以方便的执行应用部署和系统管理等操作
fabric2 依赖于paramiko 进行 ssh 交互,fabric2 的设计思路是通过几个 API 接口来完成所有的部署
安装:pip install fabric2 -i "https://pypi.doubanio.com/simple/"
fabric2 的简单使用
from fabric2 import Connectiondef deploy():# 如果服务器配置了ssh免密码登录,就不需要 connect_kwargs 来指定密码conn = Connection("root@192.168.44.13", connect_kwargs={"password": "123456"})conn.run("ls")with conn.cd('/home'):conn.run("mkdir testdir")with conn.cd('/home/testdir'):conn.run('mkdir aaa')conn.put('test', '/home/testdir') # 上传文件if __name__ == '__main__':deploy()
Connection 参数详解
def __init__(self,host, # 主机 ipuser=None, # 用户名port=None, # ssh 端口,默认 22config=None, # 登录配置文件gateway=None, # 连接网关forward_agent=None, # 是否开启 agent forwardingconnect_timeout=None, # 设置超时connect_kwargs=None, # 设置密码登录 connect_kwargs={"password": "123456"}# 还是密钥登录 connect_kwargs={"key_filename": "/home/myuser/.ssh/id_rsa"}inline_ssh_env=None,)
conn 对象属性
run # 执行远程命令,如:run('uname -a')
cd # 切换远程目录,如:cd('/root'); with conn.cd('/root'),继承这个状态
put # 上传本地文件到远程主机,如:put('/root/test.py','/root/test.py')
get # 获取服务器上文件,如:get('/root/test.py')
sudo # sudo方式执行远程命令,如: sudo('service docker start')
local # 执行本地命令,如:conn.local('ls')
二、 fabric2 对多台机器使用
对多台机器使用时,Connection
from fabric2 import Connectionfor host in ('root@192.168.44.20','root@192.168.44.21','root@192.168.44.22'):result = Connection(host,connect_kwargs={'password':'123456'}).run('uname -s')print("{}: {}".format(host,result.stdout.strip()))
输出结果
Linux
root@192.168.44.20: Linux
Linux
root@192.168.44.21: Linux
Linux
root@192.168.44.22: Linux
对多台机器使用时,SerialGroup
from fabric2 import SerialGrouppool = SerialGroup('root@192.168.44.20','root@192.168.44.21','root@192.168.44.22',connect_kwargs={'password':'123456'})
print(pool)
pool.run('uname -s')
for conn in pool:conn.run('mkdir testfiles')
扩展,运行本地命令
import invokeinvoke.run('ls')
三、使用示例:
From:https://www.walkerfree.com/article/183
import getpass
from fabric import Connection, task@task
def pack(c):# 这里的c参数我理解为是Connection连接的本地 然后根据setup.py进行项目打包c.run('python setup.py release sdist --format=gztar')@task
def deploy(c):# 输入服务器的登录用户名user = raw_input('Input login user name: ')# 输入服务器的登录地址host = raw_input('Input login host: ')# 输入服务器的项目目录地址root = raw_input('Input project root path:')# 输入服务器的登录密码user_pass = getpass.getpass('Input login user pass:')# 获取包的全名称result = c.run('python setup.py --fullname', hide=True)dist = result.stdout.strip()filename = '%s.tar.gz' % dist# 获取包的名称 - 这个名称可以根据自己的需求来自定义,这里主要是为了下面supervisor启动时使用result = c.run('python setup.py --name', hide=True)name = result.stdout.strip()# 远端服务器连接创建remote = Connection('%s@%s' % (user, host),connect_kwargs={"password": user_pass})# 上传文件到远端服务器remote.put('./dist/%s' %filename, remote='%s' % root)# 在远端服务器上执行下面命令 - 这个会默认输出你在远端服务器展示的信息result = remote.run('cd %s &&\source .env/bin/activate &&\ls -al && type python &&\pip install %s &&\supervisorctl restart walkerfree' % (root, filename))
使用方式如下:fab pack deploy
这个命令其实也可以分布执行:
fab pack
fab deploy
Fabric 自升级至2.x后,API大变,fab工具也逐渐边缘化,其编程方式也与普通的python脚本逐渐趋同。以下是Fabric1.x与2.x大致的差异与变化,用 python 脚本展示:
#!/bin/python
# coding:utf-8
from fabric import ThreadingGroup as Group
import ConfigParser#fabric2.x不再支持1.x中的from fabric.colors import *方式在终端上输出有颜色的执行结果
#可以通过导入blessings包的方式来完成相关操作
from blessings import Terminal
t = Terminal()def run_command(command_section, connection):for option in cf.options(command_section):#在shell中执行grep命令后,如果没有相关信息输出,grep的返回值为0,需要添加warn=True来#避免UnexpectedExit异常的触发result = connection.run(cf.get(command_section, option), warn=True)if option.find('grep', 0) != -1 and result.stdout == '':print(option + " exec complete!")if __name__ == '__main__':#可以通过额外定义配置文件的方式,实现执行命名与脚本代码的分离cf = ConfigParser.ConfigParser()cf.read('command.conf')#以Group执行的方式也发生了变化,具体可参考api文档for aims_connection in Group('aims@10.99.1.24'):#通过红色加粗下划线的方式显示print t.red_underline_bold(str(aims_connection))run_command("common_command", aims_connection)run_command("aims_command", aims_connection)for ib_connection in Group('ibuser@10.99.1.27'):print t.red_underline_bold(str(ib_connection))run_command("common_command", ib_connection)run_command("ib_command", ib_connection)
配置文件:
[common_command]
df_command = df -h | awk 'NR > 1 && $5+0 > maxspace {maxspace = $5+0;name = $6} END { print name " has " maxspace"%"} '[aims_command]
grep_syserror_command = grep -i error /var/log/syslog
grep_syswarn_command = grep -i warning /var/log/syslog[ib_command]
jboss_warn = grep -i warn /opt/logs/services/jboss.log | grep -v 'null'