Python 自动化运维与远程部署:fabric
0X00 安装fabric
使用pip可以轻松地安装fabric
1pip install fabric0X01 初次调用
在当前目录下创建一个名为fabfile.py的文件,填写文件内容如下:
1# coding=utf-8
2import fabric
3
4
5def test():
6 print 'hello,world'然后在当前目录下执行命令fab test就可以看到一条hello,world输出了。
0X02 浅显的道理
根据上面简单的例子可以看出来fab命令执行的时候会默认找到当前目录下的fabfile.py文件,找到后会用fab命令的参数去匹配fabfile.py中的函数名,执行相应的功能。
实际上当前目录可以没有
fabfile.py,如果当前目录的上级目录中有fabfile.py是会采用上级目录中的fabfile.py的。而且文件名也不一定用fabfile.py,假设取了一个名为asdf.py的文件,那么只需要执行fab -f asdf.py就可以采用这个fabfile了。
0X03 执行本地命令
作为一个可以用来自动化运维和远程部署的库,运行本地命令是一个必不可少的功能。
1# coding=utf-8
2
3from fabric.api import local
4
5
6def list_home_dir():
7 local('ls ~/.')这里的local方法就是执行本地命令,并将输出打印出来。然后运行fab list_home_dir就可以看到自己~目录下的文件们了。当然,也可以带参数的。
1def cp_file(file_a, file_b):
2 local('cp %s %s' % (file_a, file_b))调用这个方法的时候可以通过fab cp_file:"file_a=~/hello.py,file_b=~/hello_b.py"这个命令将~/hello.py复制到hello_b.py。
0X04 执行远程命令
fabric用处最大的一点就是远程执行命令了。使用下面这段代码,运行fab list_home后fabric会使用你提供的登录信息通过SSH登录到远程机器上执行ls ~/.的命令。其中run()就是在远程机器上执行命令。
1# coding=utf-8
2
3from fabric.api import run, env
4
5env.hosts = ['qcloud.just666.cn', ]
6env.user = 'root'
7env.password = '5L2g5b2T5oiR5YK75ZWK'
8
9def list_home():
10 run('ls ~/.')0X05 多台机器执行相同的命令
有的时候我们有多台机器,需要执行相同的命令,这种时候就可以用env.passwords来解决问题。通过hosts指定用户名和主机,用passwords指定密码,就可以同时登录到多台机器上了。
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4from fabric.api import env, run
5
6# 指定主机
7env.hosts = [
8 'root@qcloud.just666.cn',
9 'root@aliyun.just666.cn',
10 'root@aws.just666.cn',
11]
12
13# 指定密码
14env.passwords = {
15 'root@qcloud.just666.cn': '5L2g5b2T5oiR5YK75ZWK',
16 'root@aliyun.just666.cn': '5L2g5b2T5oiR5YK75ZWK',
17 'root@aws.just666.cn': '5L2g5b2T5oiR5YK75ZWK',
18}
19
20def hello():
21 run('ls ~/.')其实我也不是很懂,既然env.passwords都已经制定了用户名,主机和密码为什么还要用hosts再指定一次呢?不是很懂,注释过hosts,就不能用了。
0X06 多台机器执行不同命令
不过通常情况下我们是有不止一台远程机器的,要不然也不会需要什么自动化了。那么假设我们有三台机器,分别是mysql/apache/nginx这三个服务,那么我们可以这么写脚本。这样我们可以通过fab start_firewalld启动三台机器的防火墙,使用fab start_mysql/start_httpd/start_nginx分别启动在这三台机器上的三个服务。
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4from fabric.api import env, run, roles
5
6env.hosts = [
7 'root@mysql.just666.cn',
8 'root@apache.just666.cn',
9 'root@nginx.just666.cn',
10]
11
12env.passwords = {
13 'root@mysql.just666.cn': 'zhangHAO8',
14 'root@apache.just666.cn': '5L2g5b2T5oiR5YK75ZWK',
15 'root@nginx.just666.cn': '5L2g5b2T5oiR5YK75ZWK',
16}
17
18env.roledefs = {
19 'all': [
20 'root@mysql.just666.cn',
21 'root@apache.just666.cn',
22 'root@nginx.just666.cn',
23 ],
24 'mysql': ['root@mysql.just666.cn', ],
25 'apache': ['root@apache.just666.cn', ],
26 'nginx': ['root@nginx.just666.cn', ],
27}
28
29@roles('all')
30def start_firewalld():
31 run('systemctl start firewalld')
32
33@roles('mysql')
34def start_mysql():
35 run('systemctl start mysql')
36
37@roles('apache')
38def start_httpd():
39 run('systemctl start httpd')
40
41@roles('nginx')
42def start_nginx():
43 run('systemctl start nginx')0X07 并发任务
通常情况下fabric是穿行执行任务的,假设有100台机器要执行相同的命令,虽然我们批量化了,但是他们依旧是串行的,导致效率比较低。这种时候我们可以采用@parallel装饰器来使方法变成并行的。比如有一个方法def test_speed用来测试机器的网速,需要持续一分钟才行,并且有很多台机器,那么这个@parallel就可以发挥作用了。
1from fabric.api import parallel
2
3@parallel
4def test_speed():
5 run('test_speed')此时这些任务就是并行的了,会快很多。不过如果真的有非常多的机器要并行,那么fabric可能扛不住,可以给并行数量设置一个上限@parallel(pool_size=10),这样就是最高10个并行任务了。
0X08 传文件
文件传输用的是scp的原理,分成两个方法,分别是get/put,用法也非常简单就像普通的cp一样。get('remote_file', 'local_file')和put('local_file', 'remote_file')
1from fabric.api import env, get, put
2
3env.hosts = ['qcloud.just666.cn', ]
4env.user = 'root'
5env.password = '5L2g5b2T5oiR5YK75ZWK'
6
7def get_vimrc():
8 get('~/.vimrc', '~/.vimrc')
9
10def put_vimrc():
11 put('~/.vimrc', '~/.vimrc')0X09 切目录
在fabric中切目录要配合Python的with语法使用。共有cd/lcd这两种切目录方法,对应的是远程目录和本地目录。
1from fabric.api import env, cd, lcd
2
3env.hosts = ['qcloud.just666.cn', ]
4env.user = 'root'
5env.password = '5L2g5b2T5oiR5YK75ZWK'
6
7def list_local_dir():
8 with lcd('/'): # 切到本地根目录
9 local('ls') # 在目录下执行命令
10 with lcd('~'): # 切到本地主目录
11 local('ls') # 在目录下执行命令
12
13def list_remote_dir():
14 with cd('/'): # 切到远程根目录
15 run('ls') # 在目录下执行命令
16 with cd('~'): # 切到远程主目录
17 run('ls') # 在目录下执行命令0X0A PATH
有的时候我们需要临时添加PATH,可以通过这种方法。
1from fabric.api import env, run, path
2
3env.hosts = ['qcloud.just666.cn', ]
4env.user = 'root'
5env.password = '5L2g5b2T5oiR5YK75ZWK'
6
7def hello():
8 with path('/home/shawn/.envs/study_django/bin/'): # 添加目录到PATH中
9 run('echo $PATH') # 查看新的PATH
10 run('echo $PATH') # 退出去后PATH也被删除了0X0B 环境变量
如果要临时修改环境变量的话可以这样子:
1from fabric.api import env, run, local, shell_env
2
3env.hosts = ['qcloud.just666.cn', ]
4env.user = 'root'
5env.password = '5L2g5b2T5oiR5YK75ZWK'
6
7def hello():
8 with shell_env(JAVA_HOME='/opt/oracle/java'):
9 run('echo $JAVA_HOME') # 远程机器的环境变量被修改了
10 local('echo $JAVA_HOME') # 本地的环境变量也被临时修改了。修改只是暂时的,退出
with之后就会恢复原状的。
0X0C 带颜色输出
有的时候为了便与查看输出结果,我们可能会需要用不同颜色的字标示不同的内容。比如用红色标示失败,黄色标示警告,绿色标示成功等。fabric也可以轻松实现这个功能的。
1from fabric.colors import *
2
3def test_color():
4 print green("OK.")
5 print yellow("Warning")
6 print red("Error")如果这篇文章对你有帮助,可以请我喝杯咖啡 ☕
评论