介紹
Fabric是基于Python(2.7,3.4+以上版本)實現的SSH命令行工具卵凑,簡化了SSH的應用程序部署及系統(tǒng)管理任務所踊,它提供了系統(tǒng)基礎的操作組件箫措,可以實現本地或遠程shell命令,包括命令執(zhí)行垫桂、文件上傳鲜戒、下載及完整執(zhí)行日志輸出等功能专控。Fabric在paramiko的基礎上做了更高一層的封裝,操作起來會更加簡單遏餐。
安裝
- python2版本:pip install fabric
- python3版本:pip install fabric3
參數介紹
fab作為Fabric程序的命令行入口踩官,提供了豐富的參數調用,命令格式如下:
fab [options] <command>[:arg1,arg2-val2,host=foo,host='h1;h2'...]...
常用參數介紹:
- -l:顯示定義好的任務函數名;
- -f:指定fab入口文件境输,默認入口文件名為fabfile.py;
- -g:指定網關(中轉)設備蔗牡,比如堡壘機環(huán)境,填寫堡壘機IP即可嗅剖;
- -H:指定目標主機辩越,多態(tài)主機用","號分隔;
- -P:以異步并行方式運行多主機任務信粮,默認為串行運行黔攒;
- -R:指定role(角色),以角色名區(qū)分不同業(yè)務組設備强缘;
- -t:設置設備連接超時時間(秒)督惰;
- -T:設置遠程主機命令執(zhí)行超時時間(秒);
- -w:當命令執(zhí)行失敗旅掂,發(fā)出警告赏胚,而非默認中止任務。
全部參數如下:
Options:
-h, --help show this help message and exit
-d NAME, --display=NAME
print detailed info about command NAME
-F FORMAT, --list-format=FORMAT
formats --list, choices: short, normal, nested
-I, --initial-password-prompt
Force password prompt up-front
--initial-sudo-password-prompt
Force sudo password prompt up-front
-l, --list print list of possible commands and exit
--set=KEY=VALUE,... comma separated KEY=VALUE pairs to set Fab env vars
--shortlist alias for -F short --list
-V, --version show program's version number and exit
-a, --no_agent don't use the running SSH agent
-A, --forward-agent forward local agent to remote end
--abort-on-prompts abort instead of prompting (for password, host, etc)
-c PATH, --config=PATH
specify location of config file to use
--colorize-errors Color error output
-D, --disable-known-hosts
do not load user known_hosts file
-e, --eagerly-disconnect
disconnect from hosts as soon as possible
-f PATH, --fabfile=PATH
python module file to import, e.g. '../other.py'
-g HOST, --gateway=HOST
gateway host to connect through
--gss-auth Use GSS-API authentication
--gss-deleg Delegate GSS-API client credentials or not
--gss-kex Perform GSS-API Key Exchange and user authentication
--hide=LEVELS comma-separated list of output levels to hide
-H HOSTS, --hosts=HOSTS
comma-separated list of hosts to operate on
-i PATH path to SSH private key file. May be repeated.
-k, --no-keys don't load private key files from ~/.ssh/
--keepalive=N enables a keepalive every N seconds
--linewise print line-by-line instead of byte-by-byte
-n M, --connection-attempts=M
make M attempts to connect before giving up
--no-pty do not use pseudo-terminal in run/sudo
-p PASSWORD, --password=PASSWORD
password for use with authentication and/or sudo
-P, --parallel default to parallel execution method
--port=PORT SSH connection port
-r, --reject-unknown-hosts
reject unknown hosts
--sudo-password=SUDO_PASSWORD
password for use with sudo only
--system-known-hosts=SYSTEM_KNOWN_HOSTS
load system known_hosts file before reading user
known_hosts
-R ROLES, --roles=ROLES
comma-separated list of roles to operate on
-s SHELL, --shell=SHELL
specify a new shell, defaults to '/bin/bash -l -c'
--show=LEVELS comma-separated list of output levels to show
--skip-bad-hosts skip over hosts that can't be reached
--skip-unknown-tasks skip over unknown tasks
--ssh-config-path=PATH
Path to SSH config file
-t N, --timeout=N set connection timeout to N seconds
-T N, --command-timeout=N
set remote command timeout to N seconds
-u USER, --user=USER username to use when connecting to remote hosts
-w, --warn-only warn, instead of abort, when commands fail
-x HOSTS, --exclude-hosts=HOSTS
comma-separated list of hosts to exclude
-z INT, --pool-size=INT
number of concurrent processes to use in parallel mode
編寫方式
全局屬性
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功能一樣温技,區(qū)別在于不同主機不同密碼的應用場景,需要注意的是扭粱,配置passwords是需配置用戶舵鳞、主機、端口等信息琢蛤,如下方式:
env.passwords = {
'root@192.168.56.131:22':'1234567',
'root@192.168.56.132:22':'1234567',
'root@192.168.56.133:22':'1234567',
'root@192.168.56.134:22':'1234567'
}
- 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組主機區(qū)分開來傻寂,定義如下:
env.roledefs = {
'webservers':['192.168.56.131','192.168.56.132','192.168.56.133'],
'dbserver':['192.168.56.134','192.168.56.135']
}
不同角色執(zhí)行不同的任務函數
引用時使用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)
常用API
Fabric提供了一組簡單但功能強大的fabric.api命令集疾掰,簡單地調用這些API就能完成大部分應用場景需求。Fabric常用方法及說明如下:
- local:執(zhí)行本地命令徐紧,如:local('uname -s');
- lcd:切換本地目錄个绍,如:lcd('/home');
- cd:切換遠程目錄浪汪,如:cd('/data/logs')巴柿;
- run:執(zhí)行遠程命令,如:run('free -m')死遭;
- sudo:sudo方式執(zhí)行遠程命令广恢,如: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不可見税稼,純業(yè)務邏輯;
- runs_once:函數修復符味悄,標識的函數只會執(zhí)行一次,不受多臺主機影響塌鸯。
簡單實例
查看遠程主機信息
本示例調用local()方法執(zhí)行本地(主控端)命令侍瑟,添加"@runs_once"修飾符保證該任務函數只執(zhí)行一次。調用run()方法執(zhí)行遠程命令丙猬。
- test01.py
from fabric.api import *
env.user = 'devops'
env.hosts = ['localhost']
env.password = '1234567'
@runs_once # 查看本地系統(tǒng)信息涨颜,當有多臺主機時只運行一次
def local_task(): # 本地任務函數
local("uname -a")
- 運行及結果
fab -f simple1.py local_task
[localhost] Executing task 'local_task'
[localhost] local: uname -a
Linux devops-virtual-machine 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Done.
動態(tài)獲取遠程目錄列表
本示例使用"@task'修復符標志入口函數go()對外部可見,配合"@runs_once"修飾符接受用戶輸入茧球,最后調用worktask()任務函數實現遠程命令執(zhí)行咐低。
- test02.py
from fabric.api import *
env.user = 'root'
env.hosts = ['192.168.56.11','192.168.56.12']
env.password = '1234567'
@runs_once # 主機遍歷過程中,只有第一臺觸發(fā)此函數
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)
該示例實現了一個動態(tài)輸入遠程目錄名稱袜腥,再獲取目錄列表的功能见擦,由于我們只要求輸入一次,在顯示所有主機上該目錄的列表信息羹令,調用一個子函數input_raw()同時配置@runs_once修復符來達到此目的鲤屡。
- 運行及結果
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 4
[192.168.56.11] out: -rw-------. 1 root root 1273 May 29 11:47 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 4
[192.168.56.12] out: -rw-------. 1 root root 1273 May 29 11:59 anaconda-ks.cfg
[192.168.56.12] out:
Done.
Disconnecting from 192.168.56.11... done.
Disconnecting from 192.168.56.12... done.
網關模式文件上傳與執(zhí)行
本示例通過Fabric的env對象定義網關模式,即俗稱的中轉福侈、堡壘機環(huán)境酒来。定義格式為"env.gateway='192.168.56.11'",其中IP“192.168.56.11”為堡壘機IP,再結合任務韓素實現目標主機文件上傳與執(zhí)行的操作肪凛。
- test03.py
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堰汉,作為文件上傳、執(zhí)行的中轉設備
env.hosts = ['192.168.56.12','192.168.56.13']
env.passwords = {
'root@192.168.56.11:22':'1234567', #堡壘機賬號信息
'root@192.168.56.12:22':'1234567',
'root@192.168.56.13:22':'1234567'
}
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(): #執(zhí)行遠程命令伟墙,安裝nginx
with cd(r_pack_path):
run("tar -xvf nginx-1.6.3.tar.gz")
with cd("nginx-1.6.3/"): #使用with繼續(xù)繼承/tmp/install目錄位置狀態(tài)
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.3.tar.gz -> /tmp/install/nginx-1.6.3.tar.gz
[192.168.56.12] run: tar -xvf nginx-1.6.3.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[1]: Leaving directory `/tmp/install/nginx-1.6.3'
[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.3.tar.gz -> /tmp/install/nginx-1.6.3.tar.gz
[192.168.56.13] run: tar -xvf nginx-1.6.3.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[1]: Leaving directory `/tmp/install/nginx-1.6.3'
[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.3.tar.gz -> /tmp/install/nginx-1.6.3.tar.gz
[192.168.56.13] put: /home/install/nginx-1.6.3.tar.gz -> /tmp/install/nginx-1.6.3.tar.gz
[192.168.56.12] run: tar -xvf nginx-1.6.3.tar.gz
....
....
....
[192.168.56.12] out: nginx-1.6.3/html/index.html
[192.168.56.12] out: nginx-1.6.3/README
[192.168.56.12] out: nginx-1.6.3/nginx_install.sh
[192.168.56.12] out: nginx-1.6.3/configure
[192.168.56.12] out:
[192.168.56.12] run: ./nginx_install.sh
[192.168.56.13] run: tar -xvf nginx-1.6.3.tar.gz
[192.168.56.13] out: nginx-1.6.3/
[192.168.56.13] out: nginx-1.6.3/src/
....
....
....
[192.168.56.12] out: make[1]: Leaving directory `/tmp/install/nginx-1.6.3'
[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[1]: Leaving directory `/tmp/install/nginx-1.6.3'
[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:
文件打包、上傳與校驗
我們時常做一些文件包分發(fā)的工作戳葵,實施步驟一般是先壓縮打包就乓,在批量上傳至目標服務器,最后做一致性校驗。本示例通過put()方法實現文件的上傳生蚁,通過對比本地與遠程主機文件的md5噩翠,最終實現文件一致性校驗。
- simple5.py
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':'1234567',
'root@192.168.56.13:22':'1234567',
}
@runs_once
def tar_task(): #本地打包任務函數邦投,只執(zhí)行一次
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(上傳)出現異常時繼續(xù)執(zhí)行伤锚,非終止
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!") #出現異常時,確認用戶是否繼續(xù)志衣,(Y繼續(xù))
@task
def check_task(): #校驗文件任務函數
with settings(warn_only=True):
#本地local命令需要配置capture=True才能捕獲返回值
lmd5 = local("md5sum /home/devops/devops/devops.tar.gz",capture=True).split(' ')[0]
rmd5 = run("md5sum /root/devops/devops.tar.gz").split(' ')[0]
if lmd5 == rmd5: #對比本地及遠程文件md5信息
prompt("OK")
else:
prompt("ERROR")
@task
def go():
tar_task()
put_task()
check_task()
- 運行及結果
fab -f simple5.py go
運行結果如下:(提示此程序不支持-P參數并行執(zhí)行屯援、如需并行執(zhí)行,程序需要做調整)
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業(yè)務服務環(huán)境
本示例通過env.roledefs定義不同主機角色蠢涝,在使用"@roles('webservers')"修復符綁定到對應的任務函數,實現不同角色主機的部署差異阅懦。
- simple6.py
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':'1234567',
'root@192.168.56.12:22':'1234567',
'root@192.168.56.13:22':'1234567',
}
@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(): #部署公共類環(huán)境和二,如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
執(zhí)行結果如下所示:
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: --2018-06-23 20:32:30-- http://mirrors.aliyun.com/repo/epel-7.repo
[192.168.56.11] out: --2018-06-23 20:32:30-- http://mirrors.aliyun.com/repo/epel-7.repo
[192.168.56.13] out: --2018-06-23 20:32:30-- 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 235 mysqld on
Done.
生產環(huán)境代碼包發(fā)布管理
程序生產環(huán)境的發(fā)布是業(yè)務上線的最后一個環(huán)境耳胎,要求具備源碼打包惯吕、發(fā)布、切換怕午、回滾废登、版本管理等功能。本示例實現了這一套流程功能郁惜,其中版本切換與回滾使用了Linux下的軟鏈接實現堡距。
- pro.py
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':'1234567',
'root@192.168.56.13:22':'1234567',
}
env.project_dev_source = '/data/dev/Lwebadmin/' #開發(fā)服務器項目主目錄
env.project_tar_source = '/data/dev/releases/' #開發(fā)服務器項目壓縮包存儲目錄
env.project_pack_name = 'release' #項目壓縮包前綴,文件名為release.tar.gz
env.deploy_project_root = '/data/www/Lwebadmin/' #項目生產環(huán)境主目錄
env.deploy_release_dir = 'releases' #項目發(fā)布目錄兆蕉,位于主目錄下面
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)) #創(chuàng)建版本目錄
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): #刪除軟鏈接虎韵,重新創(chuàng)建并指定軟鏈接源目錄易稠,新版本生效
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)) #刪除軟鏈接,重新創(chuàng)建并指定軟鏈接源目錄包蓝,新版本生效
print(green("rollback sucess!"))
@task
def go(): #自動化程序版本發(fā)布入口函數
tar_source()
put_package()
make_symlink()
在生產環(huán)境中將站點的根目錄指向"/data/www/Lwebadmin/current",由于使用Linux軟鏈接做切換驶社,管理員的版本發(fā)布、回滾操作用戶無感知测萎。