Fabric是一个Python库和命令行工具,旨在为应用部署和系统管理任务的SSH的流水线式操作,使之更加高效和方便。Fabric提供了一套基本的执行本地和远程shell命令、上传和下载文件的操作,包括一些辅助函数,例如驱动正在运行的用户输入或者放弃执行。
Fabric通过把大量频繁使用的SSH操作写入到一个脚本中(fabric.py),来远程执行一些应用部署或者系统维护的任务。Fabric是类似paramiko的一个库,是对paramiko的再次封装,所以比使用paramiko更简单。
Fabric的优点:
角色定义
代码易读
封装了本地、远程操作
参数灵活,能偶动态指定host/role等,还有并发执行(基于multiprocessing)
完整的日志输出
在Linux下安装方法:
使用pip来安装
1 2 | yum install python - pip - y pip install fabric |
Fabric通过命令行工具fab来执行定义在fabfile.py中的任务,常用的配置和函数如下:
常用的fab命令选项和参数:
-l 显示可用的task
-H 指定host,多个host用逗号分开
-R 指定role,多个role用逗号分开
-P 并分数,默认是串行
-w warn_only,默认为遇到异常直接放弃执行并退出
-f 指定入口文件,fab默认入口文件是:fabfile.py
fabfile.py文件中常用配置和函数:
env.host 主机ip,也可以使用fab选项-H参数来指定
env.password SSH密码,若已经设置好无密码登录,则可以忽略
env.roledefs 角色分组,如:{'web': ['x', 'y'], 'db': ['z']}
local('pwd') 执行本地命令
lcd('/tmp') 切换本地目录
cd('/tmp') 切换远程目录
run('uname -s') 执行远程命令
sudo('service httpd restart') 执行远程sudo,注意pty选项
env.exclude_hosts=['10.1.6.159'] 排除10.1.6.159
fabric.operations.open_shell() 打开远程shell界面。
get 是下载
put 是上传
下面来一些例子:
1 2 3 4 5 6 7 8 9 10 11 12 | #/usr/bin/python #coding:utf8 from fabric.api import * from fabric.colors import * from fabric.context_managers import * env.hosts = [ '10.1.6.186' , '10.1.6.159' ] env.password = 'xxxxxx' def task1(): with cd( '/home/guol' ): run( 'ls -l' ) |
不同的机器执行不同的task:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #!/usr/bin/python from fabric.api import * from fabric.colors import * from fabric.context_managers import * env.roledefs = { 'web1' :[ '10.1.6.186' ], 'web2' :[ '10.1.6.159' ]} env.password = 'xxxxxx' ##需要配置密码相同,,,, @roles ( 'web1' ) def task1(): with cd( '/home/guol' ): run( 'ls -l' ) @roles ( 'web2' ) def task2(): print (green( "I'm fabric" )) def deploy(): execute(task1) execute(task2) 执行结果: root@vm11: / tmp # fab deploy [ 10.1 . 6.186 ] Executing task 'task1' [ 10.1 . 6.186 ] run: ls - l [ 10.1 . 6.186 ] out: total 0 [ 10.1 . 6.186 ] out: - rw - r - - r - - 1 root root 0 Dec 21 13 : 32 186 - local [ 10.1 . 6.186 ] out: [ 10.1 . 6.159 ] Executing task 'task2' I'm fabric Done. Disconnecting from 10.1 . 6.186 ... done. |
farbic的环境变量:
fabric的环境变量有很多,存放在一个字典中,
fabric.state.env,而它包含在fabric.api中。
为了方便,我们一般使用env来指代环境变量。
env环境变量可以控制很多fabric的行为,一般通过env.xxx可以进行设置。
fabric默认使用本地用户通过ssh进行连接远程机器,不过你可以通过env.user变量进行覆盖。
当你进行ssh连接时,fabric会让你交互的让你输入远程机器密码,如果你设置了env.password变量,则就不需要交互的输入密码。
下面介绍一些常用的环境变量:
abort_on_prompts 设置是否运行在交互模式下,例如会提示输入密码之类,默认是false
connection_attempts fabric尝试连接到新服务器的次数,默认1次
cwd 目前的工作目录,一般用来确定cd命令的上下文环境
disable_known_hosts 默认是false,如果是true,则会跳过用户知道的hosts文件
exclude_hosts 指定一个主机列表,在fab执行时,忽略列表中的机器
fabfile 默认值是fabfile.py在fab命令执行时,会自动搜索这个文件执行。
host_string 当fabric连接远程机器执行run、put时,设置的user/host/port等
hosts 一个全局的host列表
keepalive 默认0 设置ssh的keepalive
loacl_user 一个只读的变量,包含了本地的系统用户,同user变量一样,但是user可以修改
parallel 默认false,如果是true则会并行的执行所有的task
pool_size 默认0 在使用parallel执行任务时设置的进程数
password ssh远程连接时使用的密码,也可以是在使用sudo时使用的密码
passwords 一个字典,可以为每一台机器设置一个密码,key是ip,value是密码
path 在使用run/sudo/local执行命令时设置的$PATH环境变量
port 设置主机的端口
roledefs 一个字典,设置主机名到规则组的映射
roles 一个全局的role列表
shell 默认是/bin/bash -1 -c 在执行run命令时,默认的shell环境
skip_bad_hosts 默认false,为ture时,会导致fab跳过无法连接的主机
sudo_prefix 默认值"sudo -S -p '%(sudo_prompt)s' " % env 执行sudo命令时调用的sudo环境
sudo_prompt 默认值"sudo password:"
timeout 默认10 网络连接的超时时间
user ssh使用哪个用户登录远程主机
设置主机列表的方法:
hosts,在上下文环境中我们称hosts为"host strings"
strings指定了username、hostname、port等
组合username@hostname:port。username和port可以省略,则默认使用本地用户和22端口。
strings映射单个主机,但是有时候你想把一批主机加入一个组中
roles则提供了一个定义一系列主机的方法,这个映射可以通过env.rolesdefs来设置
它必须通过fabfile进行设置才可以使用。env.roledefs['webservers'] = ['www1', 'www2', 'www3']
fabric 中传参数的类型,下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #!/usr/bin/python from fabric.api import * import fabric.operations from fabric.colors import * from fabric.context_managers import * import datetime env.passwords = { 'root@192.168.1.1:22' : 'redhat123456' , 'root@192.168.1.2:22' : 'redhat' } @hosts ( 'root@192.168.1.1:22' ) def task1(): filename = run( 'ls /root/my/' ) #查看远程目录上的文件(此例子中这个目录下只有一个a.txt) 把这个文件名传到task2上中去 get( '/root/my/*' , '/root/my' ) #下载到本地的/root/my目录下 local( 'fab task2:name=%s' % filename) #执行本地命令,并传递filename这个参数给task2 @hosts ( 'root@192.168.1.2:22' ) def task2(name = ''): #定义带参数的函数 put( '/root/my/%s' % name, '/root/my' ) #把本地的/root/my/a.txt上传到192.168.1.2的/root/my目录下 #### 运行: fab task1 单独运行task2的命令: fab task2:name = 'a.txt' |
最后再来一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #!/usr/bin/env python # -*- coding:utf-8 -*- from fabric.api import env,run,local,hosts,put,puts, cd import fabric.operations from fabric.colors import * import datetime # env.hosts = [] #下面定义三个主机 env.passwords = { 'root@192.168.10.91:22' : 'password' , 'root@11.44.119.2:22' : 'password' , 'root@11.44.119.1:22' : 'password' } @hosts ( 'root@192.168.10.91:22' ) def uploadmusic(): put( './data/*.mp3' , '/var/www/html/music/' ) #把本地/data/目录下的mp3文件上传到192.168.10.91 @hosts ( 'root@11.44.119.2:22' ) def rsyncmusic(): with cd( "/usr/local/tomcat/webapps/" ): #远程执行cd 命令,,下面是run执行的命令 run( 'pwd' ) run( 'ls /root/' ) bak_webapi = 'tar -zcf webapi_%s.tar.gz webapi' % datetime.datetime.now().strftime( "%Y%m%d%H%M" ) run(bak_webapi) put( "./data/*.txt" , "webapi/WEB-INF/classes/data/" ) run( "rm -rf webapi/WEB-INF/classes/data/index" ) run( "echo ''>/usr/local/tomcat/webapps/webapi/WEB-INF/classes/data/a.txt" ) #fabric.operations.open_shell("python /root/zhou.py") @hosts ( 'root@11.44.119.1:22' ) def shellhost(): fabric.operations.open_shell() #远程到119.1上,并打开shell |