Python3自動化運維之Fabric模版詳解

1、概要

  Fabric是基於Python(2.7,3.4+以上版本)實現的SSH命令行工具,簡化了SSH的應用程序部署及系統管理任務,它提供了系統基礎的操做組件,能夠實現本地或遠程shell命令,包括命令執行、文件上傳、下載及完整執行日誌輸出等功能。Fabric在paramiko的基礎上作了更高一層的封裝,操做起來會更加簡單。
Fabric官網地址爲:http://www.fabfile.org/。

2、Fabric安裝

Mac os及CentOS 安裝php

pip3 install fabric3

Ubuntu安裝html

devops@devops-virtual-machine:~$ python --version
Python 3.6.5
devops@devops-virtual-machine:~$ pip3 install fabric3

詳細請參閱官方文檔python

3、官方提供了一個簡單的入門實例

參考官方資料:https://github.com/fabric/fabric/tree/1.13.1mysql

http://www.fabfile.org/changelog-v1.html?highlight=1.xnginx

https://github.com/mathiasertl/fabric/git

#!/usr/bin/env python
from fabric.api import run

#定義一個任務函數,經過run方法實現遠程執行"uname -s"命令 def host_type(): run(
'uname -s')

運行結果github

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"來指定,示例:web

fab -H localhost -f host_type.py host_type

 若是目標主機未配置密鑰認證信任,將會提示輸入目標主機對應帳號登陸密碼。sql

4、fab經常使用參數

官方文檔:http://docs.fabfile.org/en/1.14/shell

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 1234567 -H localhost -- 'uname -s'
[localhost] Executing task '<remainder>'
[localhost] run: uname -s
[localhost] out: Linux
[localhost] out:


Done.
Disconnecting from localhost... done.

5、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':'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組主機區分開來,定義以下:
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:函數修復符,標識的函數只會執行一次,不受多臺主機影響。

6、示例一:查看本地與遠程主機信息

查看本地信息

本示例調用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 = '1234567'

@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.0-20-generic #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018 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 = '1234567'



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 4
[192.168.56.11] out: -rw-------. 1 root root 1273 May 29 11:47 anaconda-ks.cfg
[192.168.56.11] out:


Done.
Disconnecting from 192.168.56.11... done.

7、示例二:動態獲取遠程目錄列表

本示例使用"@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 = '1234567'


@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 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.

8、示例三:網關模式文件上傳與執行

本示例經過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':'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():                    #執行遠程命令,安裝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.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:
加P參數該爲異步並行執行,運行結果

9、示例四:文件打包、上傳與校驗

咱們時常作一些文件包分發的工做,實施步驟通常是先壓縮打包,在批量上傳至目標服務器,最後作一致性校驗。本示例經過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':'1234567',
    'root@192.168.56.13:22':'1234567',
}


@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(' ')[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參數並行執行、如需並行執行,程序須要作調整)

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.

10、示例五:部署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':'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():                          #部署公共類環境,如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: --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.

11、生產環境代碼包發佈管理

程序生產環境的發佈是業務上線的最後一個環境,要求具有源碼打包、發佈、切換、回滾、版本管理等功能。本示例實現了這一套流程功能,其中版本切換與回滾使用了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':'1234567',
    'root@192.168.56.13:22':'1234567',
}

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軟連接作切換,管理員的版本發佈、回滾操做用戶無感知。

相關文章
相關標籤/搜索