Fabric是Python的一个模块,基于SSH提供了丰富的交互接口,能够用来在本地或远程机器上自动化的执行Shell命令,很是适合用来作应用的远程部署及系统维护。php
fabric底层基于paramiko(paramiko是用于ssh链接的库)。java
$ pip install fabric
复制代码
Fabric默认的脚本文件是fabfile.py
,建立该文件并定义以hello函数:python
def hello():
print("Hello Fabric!")
复制代码
可使用参数-l
来列出当前fabfile.py
中定义了哪些任务,而后在fabfile.py
目录下执行命令能够看到输出结果:nginx
$ fab -l
Available commands:
hello
$ fab hello
Hello Fabric!
Done.
复制代码
fabfile.py中每一个函数表明一个任务,任务名即函数名。fab命令用来执行fabfile.py中定义的任务,它必须显示的指定任务名。web
任务也能够带参数,好比咱们将hello函数改成:shell
def hello(name, value):
print("Hello Fabric! %s %s." % (name, value))
复制代码
此时执行hello任务时须要传入参数:api
$ fab hello:name=Year,value=2017
复制代码
fabric默认执行的脚本是fabfile.py
,若是要换脚本文件须要使用-f
指定。好比咱们将hello任务放到script.py
中就要执行:安全
$ fab -f script.py hello:name=Year,value=2017
复制代码
fabfile.py内容以下:bash
#-*- coding:utf-8 -*-
from fabric.api import local
def taskA():
local('touch fab.out && echo "fabric" >> fab.out')
def taskB():
# capture参数能够捕获标准输出存到变量,默认为False
output = local('echo "Hello World."', capture=True)
print output
复制代码
执行任务:服务器
$ fab taskA taskB
复制代码
Fabric真正强大在于能够很方便的执行远程机器上的Shell命令,它基于SSH实现。
#-*- coding:utf-8 -*-
from fabric.api import run, env
# env被称为环境字典,用来配置一些运行环境相关的信息
env.hosts = ['192.168.1.100', '192.168.1.101']
env.user = 'user'
env.password = 'passwd'
def taskA():
run('cd /usr/local/webserver/php && ls -l')
run('sudo /usr/local/webserver/nginx/sbin/nginx -t')
复制代码
env.hosts
是设置机器列表的,也能够把用户直接写到hosts里:
env.hosts = ['user@192.168.1.100', 'user@192.168.1.101']
复制代码
若是代码中没有设置env.hosts
,也能够在执行任务时经过-H
参数进行指定:
$ fab -H 192.168.1.100 taskA
复制代码
环境字典fabric.state.env是做为全局单例实现的,为方便使用也包含在fabric.api中。env中的键一般也被称为环境变量。
几个经常使用的环境变量以下:
若是对于不一样的服务器想执行不一样的任务,上面的程序就作不到了,咱们须要对服务器定义角色:
#-*- coding:utf-8 -*-
from fabric.api import env, roles, run, execute, cd
env.roledefs = {
'dev': ['user1@10.216.224.65', 'user2@10.216.224.66'],
'online': ['user3@45.33.108.82']
}
# host strings必须由username@host:port三部分构成,缺一不可,不然运行时仍是会要求输入密码
env.passwords = {
'user1@10.216.224.65:22': 'passwd1',
'user2@10.216.224.66:22': 'passwd2',
'user3@45.33.108.82:22': 'passwd3'
}
@roles('dev')
def taskA():
with cd('/usr/local/webserver'):
run('pwd')
@roles('online')
def taskB():
run('pwd')
def task():
execute(taskA)
execute(taskB)
复制代码
而后执行task任务便可:
$ fab task
复制代码
Fabric会在dev机器上执行taskA任务,而后在online机器上执行taskB任务。@roles装饰器指定了它所装饰的任务会被哪一个角色的服务器执行。
上面的例子都是将登录密码写到脚本文件里的,这样作不安全,推荐的方法是设置SSH KEY自动登录。登录本地机器生成KEY:
$ ssh-keygen -t rsa -f ~/.ssh/id_rsa_fabric
复制代码
生成密钥对以后将公钥添加到远程服务器的~/.ssh/authorized_keys
文件中,就能够实现自动登录了。
#-*- coding:utf-8 -*-
from fabric.api import env, roles, run, execute, cd
env.hosts = ['10.216.224.65', '10.216.224.66']
env.user = 'user'
env.key_filename = '~/.ssh/id_rsa_fabric'
def taskA():
with cd('/usr/local/webserver'):
run('pwd')
复制代码
authorized_keys文件权限只全部者可写,其余用户均无写权限,不然sshd将认为不安全不容许使用该文件致使还须要输入密码认证。
Fabric的上下文管理器是一系列与Python的with语句配合使用的方法,它能够在with语句块内设置当前工做环境的上下文。
#-*- coding:utf-8 -*-
from fabric.api import env, lcd, local, cd, path, settings, shell_env, prefix, sudo, run
env.hosts = ['10.216.224.66']
env.user = 'user'
env.key_filename = '~/.ssh/id_rsa_fabric'
def task():
# 设置本地工做目录
with lcd('/usr/local/webserver'):
local('touch local.out')
# 设置远程机器的工做目录
# sudo功能相似run方法,以超级用户权限执行远程命令
with cd('/usr/local/webserver'):
sudo('touch remote.out')
# 添加远程机器的path路径
# 出了with语句path又回到原来的值
with path('/usr/local/webserver'):
run('echo $PATH')
run('echo $PATH')
# 设置Fabric环境变量参数
# fabric.api.env
# warn_only设置为True,遇到错误不会退出
with settings(warn_only=True):
run('echo $USER')
# shell_env能够用来临时设置远程和本机上的Shell环境变量
with shell_env(JAVA_HOME='/opt/java'):
run('echo $JAVA_HOME')
local('echo $JAVA_HOME')
# 设置命令执行前缀,等同于 run('echo Hi && pwd')
with prefix('echo Hi'):
run('pwd')
local('pwd')
复制代码
默认状况下,Fabric在任务遇到错误时就会退出,若是咱们但愿捕获这个错误而不是退出任务的话,就要开启warn_only参数。在上面介绍settings()上下文管理器时,咱们已经看到了临时开启warn_only的方法了,若是要全局开启,有两个方法:
$ fab -w task
复制代码
#-*- coding:utf-8 -*-
from fabric.api import env
env.warn_only = True
复制代码
如今遇到错误时,控制台会打出一个警告信息,而后继续执行后续任务。那咱们怎么捕获错误并处理呢?像local/run/sudo/get/put等函数都有返回值,当返回值的succeeded属性为True时,说明执行成功,反之就是失败;也能够检查返回值的failed属性,为True表示执行失败,有错误发生。
#-*- coding:utf-8 -*-
from fabric.api import env, local, cd, put
env.hosts = ['10.216.224.66']
env.user = 'liuzhen'
env.key_filename = '~/.ssh/id_rsa_fabric'
env.warn_only=True
def task():
with cd('/data/server'):
local('touch /data/server/README.md')
upload = put('/data/server/README.md', 'README.md')
if upload.failed:
put('/data/server/README.md', 'README.md', use_sudo=True)
复制代码
Fabric在多台机器上执行任务时默认状况下是串行的。Fabric支持在多台服务器上并行执行任务,并行能够有效的加快执行速度。开启并行执行有以下两个方法:
$ fab -P task
复制代码
#-*- coding:utf-8 -*-
from fabric.api import env
env.parallel = True
复制代码
以上是对任务并行作一个全局控制。若是只想对某一个任务作并行的话,咱们能够在任务函数上加上@parallel装饰器,这样即使全局并行未开启,被@parallel装饰的任务也会并行执行:
#-*- coding:utf-8 -*-
from fabric.api import env, run, parallel
env.hosts = ['10.216.224.65', '10.216.224.66']
env.user = 'user'
env.key_filename = '~/.ssh/id_rsa_fabric'
@parallel
def taskA():
run('echo "parallel"')
def taskB():
run('echo "serial"')
复制代码
假如全局并行已开启,咱们想让某个任务串行执行,咱们能够在任务函数上加上@serial装饰器,这样即使并行已开启,被@serial装饰的任务也会串行执行:
#-*- coding:utf-8 -*-
from fabric.api import env, run, serial
env.hosts = ['10.216.224.65', '10.216.224.66']
env.user = 'user'
env.key_filename = '~/.ssh/id_rsa_fabric'
env.parallel = True
def taskA():
run('echo "parallel"')
@serial
def taskB():
run('echo "serial"')
复制代码
Fabric常规用法这里就基本介绍完了,详细的能够参考官方文档。