Python3自动化运维之Fabric模版详解
一、概要
Fabric是基于Python(2.7,3.4+以上版本)实现的SSH命令行工具,简化了SSH的应用程序部署及系统管理任务,它提供了系统基础的操作组件,可以实现本地或远程shell命令,包括命令执行、文件上传、下载及完整执行日志输出等功能。Fabric在paramiko的基础上做了更高一层的封装,操作起来会更加简单。
Fabric官网地址为:http://www.fabfile.org/。
二、Fabric安装
Mac os及CentOS 安装
pip3 install fabric3
Ubuntu安装
devops@devops-virtual-machine:~$ python --version
Python 3.6.5
devops@devops-virtual-machine:~$ pip3 install fabric3
详细请参阅官方文档
三、官方提供了一个简单的入门实例
参考官方资料:https://github.com/fabric/fabric/tree/1.13.1
http://www.fabfile.org/changelog-v1.html?highlight=1.x
https://github.com/mathiasertl/fabric/
#!/usr/bin/env python
from fabric.api import run
#定义一个任务函数,通过run方法实现远程执行"uname -s"命令
def host_type():
run('uname -s')
运行结果
devops@devops-virtual-machine:~/devops$ fab -H localhost host_type
[localhost] Executing task 'host_type'
[localhost] run: uname -s
[localhost] Login password for 'devops':
[localhost] out: Linux
[localhost] out: Done.
Disconnecting from localhost... done.
其中,fab命令引用文件名fabfile.py,如果使用非默认文件名称,则需要通过"-f"来指定,示例:
fab -H localhost -f host_type.py host_type
如果目标主机未配置密钥认证信任,将会提示输入目标主机对应账号登录密码。
四、fab常用参数
官方文档:http://docs.fabfile.org/en/1.14/
fab作为Fabric程序的命令行入口,提供了丰富的参数调用,命令格式如下:
fab [options] <command>[:arg1,arg2-val2,host=foo,host='h1;h2'...]...
常用参数介绍。更多参数可使用fab -help查看。
- -l:显示定义好的任务函数名;
devops@devops-virtual-machine:~/devops$ fab -l
Available commands: host_type
- -f:指定fab入口文件,默认入口文件名为fabfile.py;
- -g:指定网关(中转)设备,比如堡垒机环境,填写堡垒机IP即可;
- -H:指定目标主机,多态主机用","号分隔;
- -P:以异步并行方式运行多主机任务,默认为串行运行;
- -R:指定role(角色),以角色名区分不同业务组设备;
- -t:设置设备连接超时时间(秒);
- -T:设置远程主机命令执行超时时间(秒);
- -w:当命令执行失败,发出警告,而非默认中止任务。
直接使用命令行执行远程操作,示例:
devops@devops-virtual-machine:~/devops$ fab -p -H localhost -- 'uname -s'
[localhost] Executing task '<remainder>'
[localhost] run: uname -s
[localhost] out: Linux
[localhost] out: Done.
Disconnecting from localhost... done.
五、fabfile的编写
fab命令好似结合我们编写的fabfile.py(其它文件名必须添加-f filename应用)来搭配使用的,部分命令行参数可以通过相应的方法来替代,使之更加灵活,例如"-H 192.168.56.133,192.168.56.134",我们可以通过定义env.hosts来实现,如"env.hosts=['192.168.56.133,192.168.56.134']"。fabfile的主体由多个自定义的任务函数组成,不同任务实现不同的操作逻辑。
全局属性设定
env对象的作用是定义fabfile的全局设定,支持多个属性,包含目标主机、用户名、密码、等角色,各属性说明如下:
- evn.host:定义目标主机,可以用IP或主机名表示,以Python的列表形式定义,如evn.hosts['192.168.56.133','192.168.56.134']。
- env.exclude_hosts:排除指定主机,如env.exclude_hosts=['192.168.56.133']。
- env.user:定义用户名,如env.user="root"。
- env.port:定义目标主机端口,默认为22,如env.port="22"。
- env.password:定义密码,如env.password='1234567'。
- env.passwords:与password功能一样,区别在于不同主机不同密码的应用场景,需要注意的是,配置passwords是需配置用户、主机、端口等信息,如:
env.passwords = {
'root@192.168.56.131:22':'',
'root@192.168.56.132:22':'',
'root@192.168.56.133:22':'',
'root@192.168.56.134:22':''
}
- env.gateway:定义网关(中转、堡垒机)IP,如env.gateway = '192.168.56.1'。
- env.deploy_release_dir:自定义全局变量,格式:env.+"变量名称",如env.deploy_release_dir、env.age、env.sex等。
- env.roledefs:定义角色分组,比如web组与db组主机区分开来,定义如下:
env.roledefs = {
'webservers':['192.168.56.131','192.168.56.132','192.168.56.133'],
'dbserver':['192.168.56.134','192.168.56.135']
}
引用时使用Python修饰符的形式进行,角色修饰符下面的任务函数为其作用域,下面来看一个示例:
@roles('webservers')
def webtask():
run('/etc/init.d/nginx start') @roles('dbservers')
def dbtask():
run('/etc/init.d/mysql start') @roles('webservers','dbservers')
def pubclitasj():
run('uptime') def deploy():
execute(webtask)
execute(dbtask)
execute(pubclitask)
在命令执行fab deploy就可以实现不同角色执行不同的任务函数了。
常用API
Fabric提供了一组简单但功能强大的fabric.api命令集,简单地调用这些API就能完成大部分应用场景需求。Fabric常用方法及说明如下:
- local:执行本地命令,如:local('uname -s');
- lcd:切换本地目录,如:lcd('/home');
- cd:切换远程目录,如:cd('/data/logs');
- run:执行远程命令,如:run('free -m');
- sudo:sudo方式执行远程命令,如:sudo('/etc/init.d/httpd start');
- put:上传本地文件到远程主机,如:put('/home/user.info','/data/user.info');
- prompt:获得用户输入信息,如:prompt('please input user password:');
- confirm:获得提示信息确认,如:confirm("Tests failed. Continue[Y/N]?");
- reboot:重启远程主机,如:reboot();
- @task:函数修饰符,标识的函数为fab可调用的,非标记对fab不可见,纯业务逻辑;
- runs_once:函数修复符,标识的函数只会执行一次,不受多台主机影响。
六、示例一:查看本地与远程主机信息
查看本地信息
本示例调用local()方法执行本地(主控端)命令,添加"@runs_once"修饰符保证该任务函数只执行一次。调用run()方法执行远程命令。
devops@devops-virtual-machine:~/devops$ pwd
/home/devops/devops
devops@devops-virtual-machine:~/devops$ cat simple1.py
#!/usr/bin/env python from fabric.api import * env.user = 'devops'
env.hosts = ['localhost']
env.password = '' @runs_once #查看本地系统信息,当有多台主机时只运行一次
def local_task(): #本地任务函数
local("uname -a")
通过fab命令调用local_task任务函数运行结果如下:
devops@devops-virtual-machine:~/devops$ fab -f simple1.py local_task
[localhost] Executing task 'local_task'
[localhost] local: uname -a
Linux devops-virtual-machine 4.15.--generic #-Ubuntu SMP Tue Apr :: UTC x86_64 x86_64 x86_64 GNU/Linux Done.
查看远程主机信息
devops@devops-virtual-machine:~/devops$ cat simple2.py
#!/usr/bin/env python from fabric.api import * env.user = 'root'
env.hosts = ['192.168.56.11']
env.password = '' def remote_task():
with cd('/root'): #"with"的作用是让后面的表达式的语句继承当前状态,实现"cd /root/ && ls -l'的效果
run('ls -l')
调用remote_task任务函数运行结果如下:
devops@devops-virtual-machine:~/devops$ fab -f simple2.py remote_task
[192.168.56.11] Executing task 'remote_task'
[192.168.56.11] run: ls -l
[192.168.56.11] out: total
[192.168.56.11] out: -rw-------. root root May : anaconda-ks.cfg
[192.168.56.11] out: Done.
Disconnecting from 192.168.56.11... done.
七、示例二:动态获取远程目录列表
本示例使用"@task'修复符标志入口函数go()对外部可见,配合"@runs_once"修饰符接受用户输入,最后调用worktask()任务函数实现远程命令执行。
devops@devops-virtual-machine:~/devops$ cat simple3.py
#!/usr/bin/env python from fabric.api import * env.user = 'root'
env.hosts = ['192.168.56.11','192.168.56.12']
env.password = '' @runs_once #主机遍历过程中,只有第一台触发此函数
def input_raw():
return prompt("Please input directory name:",default="/home") def worktask(dirname):
run("ls -l "+dirname) @task #限定只有go函数对fab命令可见
def go():
getdirname = input_raw()
worktask(getdirname)
该示例实现了一个动态输入远程目录名称,再获取目录列表的功能,由于我们只要求输入一次,在显示所有主机上该目录的列表信息,调用一个子函数input_raw()同时配置@runs_once修复符来达到此目的。
执行结果如下:
devops@devops-virtual-machine:~/devops$ fab -f simple3.py go
[192.168.56.11] Executing task 'go'
Please input directory name: [/home] /root
[192.168.56.11] run: ls -l /root
[192.168.56.11] out: total
[192.168.56.11] out: -rw-------. root root May : anaconda-ks.cfg
[192.168.56.11] out: [192.168.56.12] Executing task 'go'
[192.168.56.12] run: ls -l /root
[192.168.56.12] out: total
[192.168.56.12] out: -rw-------. root root May : anaconda-ks.cfg
[192.168.56.12] out: Done.
Disconnecting from 192.168.56.11... done.
Disconnecting from 192.168.56.12... done.
八、示例三:网关模式文件上传与执行
本示例通过Fabric的env对象定义网关模式,即俗称的中转、堡垒机环境。定义格式为"env.gateway='192.168.56.11'",其中IP“192.168.56.11”为堡垒机IP,再结合任务韩素实现目标主机文件上传与执行的操作。
devops@devops-virtual-machine:/home/install$ cat /home/devops/devops/simple4.py
#!/usr/bin/env python from fabric.api import *
from fabric.context_managers import *
from fabric.contrib.console import confirm env.user = 'root'
env.gateway = '192.168.56.11' #定义堡垒机IP,作为文件上传、执行的中转设备
env.hosts = ['192.168.56.12','192.168.56.13'] env.passwords = {
'root@192.168.56.11:22':'', #堡垒机账号信息
'root@192.168.56.12:22':'',
'root@192.168.56.13:22':''
} l_pack_path = "/home/install/nginx-1.6.3.tar.gz" #本地安装包路径
r_pack_path = "/tmp/install" #远程安装包路径 @task
def put_task():
run("mkdir -p /tmp/install")
with settings(warn_only=True):
result = put(l_pack_path,r_pack_path) #上传安装包
if result.failed and not confirm("put file failed, Continue[Y/N]?"):
abort("Aborint file put task!") @task
def run_task(): #执行远程命令,安装nginx
with cd(r_pack_path):
run("tar -xvf nginx-1.6.3.tar.gz")
with cd("nginx-1.6.3/"): #使用with继续继承/tmp/install目录位置状态
run("./nginx_install.sh") @task
def go(): #上传、安装
put_task()
run_task()
执行命令fab -f simple4.py go。运行结果如下:
devops@devops-virtual-machine:~/devops$ fab -f simple4.py go
[192.168.56.12] Executing task 'go'
[192.168.56.12] run: mkdir -p /tmp/install
[192.168.56.12] put: /home/install/nginx-1.6..tar.gz -> /tmp/install/nginx-1.6..tar.gz
[192.168.56.12] run: tar -xvf nginx-1.6..tar.gz
.....
.....
.....
[192.168.56.12] out: cp conf/nginx.conf '/usr/local/nginx/conf/nginx.conf.default'
[192.168.56.12] out: test -d '/usr/local/nginx/logs' || mkdir -p '/usr/local/nginx/logs'
[192.168.56.12] out: test -d '/usr/local/nginx/logs' || mkdir -p '/usr/local/nginx/logs'
[192.168.56.12] out: test -d '/usr/local/nginx/html' || cp -R html '/usr/local/nginx'
[192.168.56.12] out: test -d '/usr/local/nginx/logs' || mkdir -p '/usr/local/nginx/logs'
[192.168.56.12] out: make[]: Leaving directory `/tmp/install/nginx-1.6.'
[192.168.56.12] out: nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
[192.168.56.12] out: nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[192.168.56.12] out: [192.168.56.13] Executing task 'go'
[192.168.56.13] run: mkdir -p /tmp/install
[192.168.56.13] put: /home/install/nginx-1.6..tar.gz -> /tmp/install/nginx-1.6..tar.gz
[192.168.56.13] run: tar -xvf nginx-1.6..tar.gz
....
....
....
[192.168.56.13] out: cp conf/nginx.conf '/usr/local/nginx/conf/nginx.conf.default'
[192.168.56.13] out: test -d '/usr/local/nginx/logs' || mkdir -p '/usr/local/nginx/logs'
[192.168.56.13] out: test -d '/usr/local/nginx/logs' || mkdir -p '/usr/local/nginx/logs'
[192.168.56.13] out: test -d '/usr/local/nginx/html' || cp -R html '/usr/local/nginx'
[192.168.56.13] out: test -d '/usr/local/nginx/logs' || mkdir -p '/usr/local/nginx/logs'
[192.168.56.13] out: make[]: Leaving directory `/tmp/install/nginx-1.6.'
[192.168.56.13] out: nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
[192.168.56.13] out: nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[192.168.56.13] out: Done.
Disconnecting from 192.168.56.11... done.
Disconnecting from 192.168.56.12... done.
Disconnecting from 192.168.56.13... done.
运行结果,默认为串行运行
执行命令fab -Pf simple4.py go。运行结果如下:
devops@devops-virtual-machine:~/devops$ fab -Pf simple4.py go
[192.168.56.12] Executing task 'go'
[192.168.56.13] Executing task 'go'
[192.168.56.12] run: mkdir -p /tmp/install
[192.168.56.13] run: mkdir -p /tmp/install
[192.168.56.12] put: /home/install/nginx-1.6..tar.gz -> /tmp/install/nginx-1.6..tar.gz
[192.168.56.13] put: /home/install/nginx-1.6..tar.gz -> /tmp/install/nginx-1.6..tar.gz
[192.168.56.12] run: tar -xvf nginx-1.6..tar.gz
....
....
....
[192.168.56.12] out: nginx-1.6./html/index.html
[192.168.56.12] out: nginx-1.6./README
[192.168.56.12] out: nginx-1.6./nginx_install.sh
[192.168.56.12] out: nginx-1.6./configure
[192.168.56.12] out: [192.168.56.12] run: ./nginx_install.sh
[192.168.56.13] run: tar -xvf nginx-1.6..tar.gz
[192.168.56.13] out: nginx-1.6./
[192.168.56.13] out: nginx-1.6./src/
....
....
....
[192.168.56.12] out: make[]: Leaving directory `/tmp/install/nginx-1.6.'
[192.168.56.12] out: nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
[192.168.56.12] out: nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[192.168.56.12] out:
....
....
...
[192.168.56.13] out: make[]: Leaving directory `/tmp/install/nginx-1.6.'
[192.168.56.13] out: nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
[192.168.56.13] out: nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[192.168.56.13] out:
加P参数该为异步并行执行,运行结果
九、示例四:文件打包、上传与校验
我们时常做一些文件包分发的工作,实施步骤一般是先压缩打包,在批量上传至目标服务器,最后做一致性校验。本示例通过put()方法实现文件的上传,通过对比本地与远程主机文件的md5,最终实现文件一致性校验。
devops@devops-virtual-machine:~/devops$ cat simple5.py
#!/usr/bin/env python from fabric.api import *
from fabric.context_managers import *
from fabric.contrib.console import confirm env.user = 'root'
env.hosts = ['192.168.56.12','192.168.56.13']
env.passwords = {
'root@192.168.56.12:22':'',
'root@192.168.56.13:22':'',
} @runs_once
def tar_task(): #本地打包任务函数,只执行一次
with lcd('/home/devops/devops'):
local("tar -zcf devops.tar.gz *") @task
def put_task(): #上传文件任务函数
run("mkdir -p /root/devops")
with cd("/root/devops"):
with settings(warn_only=True): #put(上传)出现异常时继续执行,非终止
result = put("/home/devops/devops/devops.tar.gz","/root/devops/devops.tar.gz")
if result.failed and not confirm("put file failed.Continue[Y/N]?"):
abort("Aborting file put task!") #出现异常时,确认用户是否继续,(Y继续) @task
def check_task(): #校验文件任务函数
with settings(warn_only=True):
#本地local命令需要配置capture=True才能捕获返回值
lmd5 = local("md5sum /home/devops/devops/devops.tar.gz",capture=True).split(' ')[]
rmd5 = run("md5sum /root/devops/devops.tar.gz").split(' ')[]
if lmd5 == rmd5: #对比本地及远程文件md5信息
prompt("OK")
else:
prompt("ERROR") @task
def go():
tar_task()
put_task()
check_task()
执行命令fab -f simple5.py go。运行结果如下:(提示此程序不支持-P参数并行执行、如需并行执行,程序需要做调整)
devops@devops-virtual-machine:~/devops$ fab -f simple5.py go
[192.168.56.12] Executing task 'go'
[localhost] local: tar -zcf devops.tar.gz *
[192.168.56.12] run: mkdir -p /root/devops
[192.168.56.12] put: /home/devops/devops/devops.tar.gz -> /root/devops/devops.tar.gz
[localhost] local: md5sum /home/devops/devops/devops.tar.gz
[192.168.56.12] run: md5sum /root/devops/devops.tar.gz
[192.168.56.12] out: a1cf2be82647cbed0d41514bd80373de /root/devops/devops.tar.gz
[192.168.56.12] out: OK
[192.168.56.13] Executing task 'go'
[192.168.56.13] run: mkdir -p /root/devops
[192.168.56.13] put: /home/devops/devops/devops.tar.gz -> /root/devops/devops.tar.gz
[localhost] local: md5sum /home/devops/devops/devops.tar.gz
[192.168.56.13] run: md5sum /root/devops/devops.tar.gz
[192.168.56.13] out: a1cf2be82647cbed0d41514bd80373de /root/devops/devops.tar.gz
[192.168.56.13] out: OK Done.
Disconnecting from 192.168.56.12... done.
Disconnecting from 192.168.56.13... done.
十、示例五:部署LNMP业务服务环境
本示例通过env.roledefs定义不同主机角色,在使用"@roles('webservers')"修复符绑定到对应的任务函数,实现不同角色主机的部署差异。
devops@devops-virtual-machine:~/devops$ cat simple6.py
#!/usr/bin/env python from fabric.colors import *
from fabric.api import * env.user = 'root'
env.roledefs = {
'webservers':['192.168.56.11','192.168.56.12'],
'dbservers':['192.168.56.13']
} env.passwords = {
'root@192.168.56.11:22':'',
'root@192.168.56.12:22':'',
'root@192.168.56.13:22':'',
} @roles('webservers') #使用webtask任务函数引用'webservers'角色修复符
def webtask():
print(yellow('Install nginx php php-fpm...'))
with settings(warn_only=True):
run("yum -y install nginx")
run("yum -y install php-fpm php-mysql php-mbstring php-xml php-mcrypt php-gd")
run("chkconfig --levels 235 php-fpm on")
run("chkconfig --levels 235 nginx on") @roles('dbservers') #dbtask任务函数引用'dbservers'角色修复符
def dbtask():
print(yellow("Install Mysql..."))
with settings(warn_only=True):
run("yum -y install mysql mysql-server")
run("chkconfig --levels 235 mysqld on") @roles('webservers','dbservers') #publictask任务函数同时引用两个角色修复符
def publictask(): #部署公共类环境,如epel、ntp等
print(yellow("Install epel ntp...."))
with settings(warn_only=True):
run("wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo")
run("yum -y install ntp") def deploy():
execute(publictask)
execute(webtask)
execute(dbtask)
执行命令fab -Pf simple6.py deploy
devops@devops-virtual-machine:~/devops$ fab -Pf simple6.py deploy
[192.168.56.11] Executing task 'publictask'
[192.168.56.12] Executing task 'publictask'
[192.168.56.13] Executing task 'publictask'
Install epel ntp....
[192.168.56.13] run: wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
Install epel ntp....
[192.168.56.12] run: wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
Install epel ntp....
[192.168.56.11] run: wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
[192.168.56.12] out: ---- ::-- http://mirrors.aliyun.com/repo/epel-7.repo
[192.168.56.11] out: ---- ::-- http://mirrors.aliyun.com/repo/epel-7.repo
[192.168.56.13] out: ---- ::-- http://mirrors.aliyun.com/repo/epel-7.repo
....
[192.168.56.13] run: yum -y install ntp
[192.168.56.12] run: yum -y install ntp
[192.168.56.11] run: yum -y install ntp
....
....
....
[192.168.56.11] Executing task 'webtask'
[192.168.56.12] Executing task 'webtask'
Install nginx php php-fpm...
[192.168.56.11] run: yum -y install nginx
Install nginx php php-fpm...
[192.168.56.12] run: yum -y install nginx
....
....
....
[192.168.56.13] Executing task 'dbtask'
Install Mysql...
[192.168.56.13] run: rpm -ivh http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm
.....
.....
.....
[192.168.56.13] run: chkconfig --levels mysqld on Done.
十一、生产环境代码包发布管理
程序生产环境的发布是业务上线的最后一个环境,要求具备源码打包、发布、切换、回滚、版本管理等功能。本示例实现了这一套流程功能,其中版本切换与回滚使用了Linux下的软链接实现。
#!/usr/local/env python from fabric.api import *
from fabric.colors import *
from fabric.context_managers import *
from fabric.contrib.console import confirm
import time env.user = 'root'
env.host = ['192.168.56.12','192.168.56.13']
env.passwords = {
'root@192.168.56.12:22':'',
'root@192.168.56.13:22':'',
} env.project_dev_source = '/data/dev/Lwebadmin/' #开发服务器项目主目录
env.project_tar_source = '/data/dev/releases/' #开发服务器项目压缩包存储目录
env.project_pack_name = 'release' #项目压缩包前缀,文件名为release.tar.gz env.deploy_project_root = '/data/www/Lwebadmin/' #项目生产环境主目录
env.deploy_release_dir = 'releases' #项目发布目录,位于主目录下面
env.deploy_current_dir = 'current' #对外服务的当前版本软链接
env.deploy_version = time.strftime("%Y%m%d")+"v2" #版本号 @runs_once
def input_versionid(): #获得用户输入的版本号,以便做版本回滚操作
return prompt("Please input project rollback version ID:",default="") @task
@runs_once
def tar_source(): #打包本地项目主目录,并将压缩包存储到本地压缩包目录
prompt(yellow("Creating source package...."))
with lcd(env.project_dev_source):
local("tar -zcf %s.tar.gz ." %(env.project_tar_source + env.project_pack_name))
prompt(green("Creating source package success!")) @task
def put_package(): #上传任务函数
prompt(yellow("Start put package...."))
with settings(warn_only=True):
with cd(env.deploy_project_root + env.deploy_release_dir):
run("mkdir %s" %(env.deploy_version)) #创建版本目录
env.deploy_full_path = env.deploy_project_root + env.deploy_release_dir + "/" + env.deploy_version
with settings(warn_only=True): #上传项目压缩包至此目录
result = put(env.project_tar_source + env.project_pack_name + ".tar.gz",env.deploy_full_path)
if result.failed and not ("put file failed,Continue[Y/N]?"):
abort("Aborting file put task!") with cd(env.deploy_full_path): #成功解压后删除压缩包
run("tar -zxvf %s.tar.gz" %(env.project_pack_name))
run("rm -rf %s.tar.gz" %(env.project_pack_name)) print(green("Put & untar package success!")) @task
def make_symlink(): #为当前版本目录做软链接
print(yellow("update current symlink"))
env.deploy_full_path = env.deploy_project_root + env.deploy_release_dir + "/" + env.deploy_version
with settings(warn_only=True): #删除软链接,重新创建并指定软链接源目录,新版本生效
run("rm -rf %s" %(env.deploy_project_root + env.deploy_current_dir))
run("ln -s %s %s" %(env.deploy_full_path,env.deploy_project_root + env.deploy_current_dir))
print(green("make symlink success!")) @task
def rollback(): #版本回滚任务函数
print(yellow("rollback project version"))
versionid = input_versionid() #获取用户输入的回滚版本号
if versionid == '':
abort("Project version ID error,abort!") env.deploy_full_path = env.deploy_project_root + env.deploy_release_dir + "/" + versionid
run("rm -r %s" %(env.deploy_project_root + env.deploy_current_dir))
run("ln -s %s %s" %(env.deploy_full_path,env.deploy_project_root + env.deploy_current_dir)) #删除软链接,重新创建并指定软链接源目录,新版本生效
print(green("rollback sucess!")) @task
def go(): #自动化程序版本发布入口函数
tar_source()
put_package()
make_symlink()
在生产环境中将站点的根目录指向"/data/www/Lwebadmin/current",由于使用Linux软链接做切换,管理员的版本发布、回滚操作用户无感知。
Python3自动化运维之Fabric模版详解的更多相关文章
- Python3自动化运维
一.系统基础信息模块详解 点击链接查看:https://www.cnblogs.com/hwlong/p/9084576.html 二.业务服务监控详解 点击链接查看:https://www.cnbl ...
- 轻量级自动化运维工具Fabric的安装与实践
一.背景环境 在运维工作中,经常会遇到重复性的劳动,这个时候为了效率就必须要使用自动化运维工具. 这里我给大家介绍轻量级自动化运维工具Fabric,Fabric是基于Python语言开发的,是开发同事 ...
- 云计算:Linux运维核心管理命令详解
云计算:Linux运维核心管理命令详解 想做好运维工作,人先要学会勤快: 居安而思危,勤记而补拙,方可不断提高: 别人资料不论你用着再如何爽那也是别人的: 自己总结东西是你自身特有的一种思想与理念的展 ...
- 自动化运维工具fabric使用教程
摘要:当需要同时管理许多服务器时,如果我们一台一台登陆上去操作会显得费时又费力.此时我们可以用fabric这个包提供的API来编写python脚本完成服务器集群的统一管理. 核心原理:fabric为主 ...
- Python自动化运维工具-Fabric部署及使用总结
使用shell命令进行复杂的运维时,代码往往变得复杂难懂,而使用python脚本语言来编写运维程序,就相当于开发普通的应用一样,所以维护和扩展都比较简单,更重要的是python运维工具fabric能自 ...
- 如何高效地远程部署?自动化运维利器 Fabric 教程
关于 Python 自动化的话题,在上一篇文章中,我介绍了 Invoke 库,它是 Fabric 的最重要组件之一.Fabric 也是一个被广泛应用的自动化工具库,是不得不提的自动化运维利器,所以,本 ...
- Python自动化运维工具fabric的安装
使用shell命令进行复杂的运维时,代码往往变得复杂难懂,而使用python脚本语言来编写运维程序,就相当于开发普通的应用一样,所以维护和扩展都比较简单,更重要的是python运维工具fabric能自 ...
- 自动化运维利器 Fabric
Fabric 主要用在应用部署与系统管理等任务的自动化,简单轻量级,提供有丰富的 SSH 扩展接口.在 Fabric 1.x 版本中,它混杂了本地及远程两类功能:但自 Fabric 2.x 版本起,它 ...
- Linux就业技术指导(五):Linux运维核心管理命令详解
一,Linux核心进程管理命令 1.1 ps:查看进程 1.1.1 命令解释 功能说明 ps命令用于列出执行ps命令的那个时刻的进程快照,就像用手机给进程照了一张照片.如果想要动态地显示进程,就需要使 ...
随机推荐
- Linux云服务器
1. 第一步:前往阿里云官网注册账号,实名认证.进去云服务器,创建实例! 第二步:选配置,**公网IP地址选择“分配”!**如果你是首次购买主机,安全组先不必勾选,或者勾选默认的 .后面,会有安全组的 ...
- jQuery实现动态分割div—通过拖动分隔栏实现上下、左右动态改变左右、上下两个相邻div的大小
由jQuery实现上下.左右动态改变左右.上下两个div的大小,需要自己引入jquery1.8.0.min.js包 可用于页面布局. //============================ind ...
- 394. Decode String 解码icc字符串3[i2[c]]
[抄题]: Given an encoded string, return it's decoded string. The encoding rule is: k[encoded_string], ...
- node.js中通过dgram数据报模块创建UDP服务器和客户端
node.js中 dgram 模块提供了udp数据包的socket实现,可以方便的创建udp服务器和客户端. 一.创建UDP服务器和客户端 服务端: const dgram = require('dg ...
- JavaSE基础知识(2)—变量和运算符
一.变量 1.理解 概念:内存中的一块数据存储空间 2.变量的三要素 数据类型变量名变量值 3.变量的语法和使用步骤★ 步骤1:声明变量(计算机开辟一块空间) 数据类型 变量名;步骤2:为变量赋值(初 ...
- jenkins源码管理git分支参数化
多个分支来回切换构建时,每次都需要去很多个job里面改分支名称,比较费时,分支参数化后可以只改一处就ok啦 步骤: 1.进入系统管理--系统设置 2.勾选全局变量,然后输入分支变量名和对应的分支名称 ...
- c++矩阵运算库Eigen简介
C++矩阵运算库Eigen介绍 C++中的矩阵运算库常用的有Armadillo,Eigen,OpenCV,ViennaCL,PETSc等.我自己在网上搜了一下不同运算库的特点,最后选择了Eigen.主 ...
- ORM初识和数据库操作
ORM简介 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术.简单的说,ORM是通过使用描述对象和数据库之 ...
- Django跨域(前端跨域)
前情回顾 在说今天的问题之前先来回顾一下有关Ajax的相关内容 Ajax的优缺点 AJAX使用Javascript技术向服务器发送异步请求: AJAX无须刷新整个页面: 因为服务器响应内容不再是整个页 ...
- Oracle使用JDBC进行增删改查 表是否存在
Oracle使用JDBC进行增删改查 数据库和表 table USERS ( USERNAME VARCHAR2(20) not null, PASSWORD VARCHAR2(20) ) a ...