Python自動化運維工具-Fabric部署及使用總結

 

使用shell命令進行復雜的運維時,代碼每每變得複雜難懂,而使用python腳本語言來編寫運維程序,就至關於開發普通的應用同樣,因此維護和擴展都比較簡單,更重要的是python運維工具fabric能自動登陸其餘服務器進行各類操做,這種實現使用shell是很難作到的,可是使用fabric實現就很簡單,因此對於程序員的平常運維部署,建議使用python編寫腳本。Fabric是基於Python實現的SSH命令行工具,簡化了SSH的應用程序部署及系統管理任務,它提供了系統基礎的操做組件,能夠經過 SSH 的方式與遠程服務器進行自動化交互, 實現本地或遠程shell命令,包括:命令執行、文件上傳、下載及完整執行日誌輸出等功能。Fabric在Paramiko的基礎上作了更高一層的封裝,操做起來會更加簡單。Fabric官網地址爲:http://www.fabfile.org/php

一. Fabric安裝html

Linux下默認有python環境,安裝fabric有兩種方式: 一是經過pip方式安裝; 而是經過fabric源碼方式安裝.
通常選擇pip方式安裝, 安裝過程以下:

先安裝一些依賴
[root@kevin ~]# yum install make gcc gcc-c++ python-devel python-setuptools -y

安裝pip
首先下載py文件:https://bootstrap.pypa.io/get-pip.py
或者百度雲盤下載地址:https://pan.baidu.com/s/1o7KylCm      提取密碼:eucx

[root@kevin ~]# cat /etc/redhat-release 
CentOS Linux release 7.5.1804 (Core) 

[root@kevin ~]# python -V
Python 2.7.5

[root@kevin ~]# wget https://bootstrap.pypa.io/get-pip.py
[root@kevin ~]# chmod 755 get-pip.py
[root@kevin ~]# python get-pip.py
Collecting pip
  Downloading https://files.pythonhosted.org/packages/c2/d7/90f34cb0d83a6c5631cf71dfe64cc1054598c843a92b400e55675cc2ac37/pip-18.1-py2.py3-none-any.whl (1.3MB)
    100% |████████████████████████████████| 1.3MB 56kB/s 
Collecting wheel
  Downloading https://files.pythonhosted.org/packages/ff/47/1dfa4795e24fd6f93d5d58602dd716c3f101cfd5a77cd9acbe519b44a0a9/wheel-0.32.3-py2.py3-none-any.whl
Installing collected packages: pip, wheel
Successfully installed pip-18.1 wheel-0.32.3

接着使用pip安裝fabric
[root@kevin ~]# pip install fabric

稍等一會就安裝完畢了,這時輸入fab就會彈出對應的選項
[root@kevin ~]# fab --version
Fabric 2.4.0
Paramiko 2.4.2
Invoke 1.2.0

[root@kevin ~]# fab --help
Usage: fab [--core-opts] task1 [--task1-opts] ... taskN [--taskN-opts]

Core options:

  --complete                         Print tab-completion candidates for given parse remainder.
  --hide=STRING                      Set default value of run()'s 'hide' kwarg.
  --no-dedupe                        Disable task deduplication.
  --print-completion-script=STRING   Print the tab-completion script for your preferred shell (bash|zsh|fish).
  --prompt-for-login-password        Request an upfront SSH-auth password prompt.
  --prompt-for-passphrase            Request an upfront SSH key passphrase prompt.
  --prompt-for-sudo-password         Prompt user at start of session for the sudo.password config value.
  --write-pyc                        Enable creation of .pyc files.
  -c STRING, --collection=STRING     Specify collection name to load.
  -d, --debug                        Enable debug output.
  -D INT, --list-depth=INT           When listing tasks, only show the first INT levels.
  -e, --echo                         Echo executed commands before running.
  -f STRING, --config=STRING         Runtime configuration file to use.
  -F STRING, --list-format=STRING    Change the display format used when listing tasks. Should be one of: flat (default), nested, json.
  -h [STRING], --help[=STRING]       Show core or per-task help and exit.
  -H STRING, --hosts=STRING          Comma-separated host name(s) to execute tasks against.
  -i, --identity                     Path to runtime SSH identity (key) file. May be given multiple times.
  -l [STRING], --list[=STRING]       List available tasks, optionally limited to a namespace.
  -p, --pty                          Use a pty when executing shell commands.
  -r STRING, --search-root=STRING    Change root directory used for finding task modules.
  -S STRING, --ssh-config=STRING     Path to runtime SSH config file.
  -V, --version                      Show version and exit.
  -w, --warn-only                    Warn, instead of failing, when shell commands fail.

=======================================================
舒適提示:
若是安裝的是pip3, 則使用"pip3 install fabric3" 安裝fabric
=======================================================

二. Fabric 使用vue

Fabric命令說明
1) fab命令格式python

fab是fabric的命令行入口 

命令的格式爲:
# fab [options] <command>[:arg1,arg2=val2,host=foo,hosts='h1;h2',...] ...

2) fab命令經常使用參數mysql

# fab --help     查看幫助
 
 經常使用參數
-l  顯示定義好的任務函數名
-f  指定fab入口文件,默認入口文件名爲fabfile.py.. 即指定fabfile文件
-g  指定網關(中轉)設備,即HOST逗號分隔要操做的主機, 好比堡壘機環境,填寫堡壘機IP便可. 
-H  指定目標主機,多臺主機用‘,’號分隔
-p  遠程帳號的密碼,fab執行時默認使用root帳戶
-P  以異步並行方式運行多主機任務,默認爲串行運行
-R  指定role(角色),以角色名區分不一樣業務組設備
-t  設置設備鏈接超時時間(秒)
-T  設置遠程主機命令執行超時時間(秒)
-w  當命令執行失敗,發出警告,而非默認停止任務。

其餘參數:
--set=KEY=VALUE,...     逗號分隔,設置環境變量
--shortlist             簡短打印可用命令
-c PATH                 指定本地配置文件
-D                      不加載用戶known_hosts文件
-i PATH                 指定私鑰文件
-k                      不加載來自~/.ssh下的私鑰文件
--port=PORT             指定SSH鏈接端口
-R ROLES                根據角色操做,逗號分隔
-s SHELL                指定新shell,默認是'/bin/bash -l -c'
--show=LEVELS           以逗號分隔的輸出
--ssh-config-path=PATH  SSH配置文件路徑
-T N                    設置遠程命令超時時間,單位秒
-u USER                 鏈接遠程主機用戶名
-x HOSTS                以逗號分隔排除主機
-z INT                  併發進程數
 
例1:  經過遠程主機查詢172.16.50.45 (該主機的root密碼爲123456)的主機名
[root@kevin ~]# fab -f fabtest.py -p 123456 -H 172.16.50.45 -- 'hostname'

例2: 本地執行命令
[root@kevin ~]# vim fabtest.py
from fabric.api import local
def command():
    local('ls')

[root@kevin ~]# fab -f fabtest.py command
[localhost] local: ls
fabfile.py  fabfile.pyc  tab.py  tab.pyc
Done.

例3: 遠程執行命令
[root@kevin ~]# vim fabtest.py

from fabric.api import run
def command():
    run('ls')

[root@kevin ~]# fab -f fabtest.py -H 192.168.1.120 -u user command
[192.168.1.120] Executing task 'command'[192.168.1.120] run: ls
[192.168.1.120] Login password for 'user':
[192.168.1.120] out: access.log  a.py
[192.168.1.120] out:
Done.
Disconnecting from 192.168.1.120... done.

若是在多臺主機執行,只須要-H後面的IP以逗號分隔便可。

例4:  給腳本函數傳入位置參數
[root@kevin ~]# vim fabfile.py

from fabric.api import run
def hello(name="world"):
    print("Hello %s!" % name)

[root@kevin ~]# fab -H localhost hello
[localhost] Executing task 'hello'Hello world!
Done.

[root@kevin ~]# fab -H localhost hello:name=Python
[localhost] Executing task 'hello'Hello Python!
Done.

例5: 主機列表組
[root@kevin ~]# vim fabfile.py
from fabric.api import run, env
env.hosts = ['root@192.168.1.120:22', 'root@192.168.1.130:22']
env.password = '123.com'env.exclude_hosts = ['root@192.168.1.120:22']   # 排除主機
def command():
   run('ls')

[root@kevin ~]# fab command
env做用是定義fabfile全局設定,相似於變量。還有一些經常使用的屬性:


例6: 定義角色分組
[root@kevin ~]# vim install.py
from fabric.api import run, env
env.roledefs = {    'web': ['192.168.1.10', '192.168.1.20'],    'db': ['192.168.1.30', '192.168.1.40']
}
env.password = '123'@roles('web')
def task1():
   run('yum install httpd -y')
@roles('db')
def task2():
   run('yum install mysql-server -y')
def deploy():
   execute(task1)
   execute(task2)

[root@kevin ~]# fab -f install.py deploy

例7: 上傳目錄到遠程主機
[root@kevin ~]# vim haha.py
from fabric.api import *
env.hosts = ['192.168.1.120']
env.user = 'user'env.password = '123.com'

def task():
   put('/root/abc', '/home/user')
   run('ls -l /home/user')

[root@kevin ~]# fab -f haha.py task

例8: 從遠程主機下載目錄
[root@kevin ~]# vim heihei.py
from fabric.api import *
env.hosts = ['192.168.1.120']
env.user = 'user'env.password = '123.com'
def task():
   get('/home/user/b', '/opt')
   local('ls -l /opt')

[root@kevin ~]# fab -f heihei.py task

例9: 打印顏色,有助於關鍵地方醒目
[root@kevin ~]# vim bobo.py
from fabric.colors import *
def show():
   print green('Successful.')
   print red('Failure!')
   print yellow('Warning.')

[root@kevin ~]# fab -f bobo.py show

3) fabfile文件的編寫 (默認的文件名稱爲fabfile)linux

fab命令是結合fabfile.py文件(其餘文件經過-f filename 參數來引用)來搭配使用的。fab的部分命令行參數還能經過相應的方法來代替。

先來看一個小例子
[root@kevin ~]# cat fabfile.py
#!/usr/bin/env python
from fabric.api import run
 
#定義一個任務函數,經過run方法實現遠程執行"uname -s"命令
def host_type():
    run('uname -s')
 
[root@kevin ~]# 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!
若是使用的是默認文件名稱, 則fab執行命令中就不須要跟文件名.
若是使用非默認文件名稱,好比這裏不是fabfile.py, 而是host_type.py 文件, 則須要經過"-f"來指定:
[root@kevin ~]# fab -H localhost -f host_type.py host_type
 
若是目標主機未配置密鑰認證信任,將會提示輸入目標主機對應帳號登陸密碼。
 
再來看一個小例子
[root@kevin ~]# vim fabric.py
#!/usr/bin/python
# -*- coding:utf-8 -*-
  
 from fabric.api import *
  
 # 設置服務器登陸參數
 env.roledefs = {
     # 操做一致的放一組,一組執行同一個操做
     'servers1':['root@linux2:22',],
     # 第二組
     'servers2':['root@linux3:22',]
 }
  
 # 本機操做
 def localtask():
     local('/usr/local/nginx/nginx')
  
 # servers1服務器組操做
 @roles('servers1')
 def task1():
     run('/usr/local/tomcat/bin/startup.sh')
  
 # servers2 服務器組操做
 @roles('servers2')
 def task2():
     run('/usr/local/tomcat/bin/startup.sh')
  
 # 執行任務
 def doworks():
     execute(localtask)
     execute(task1)
     execute(task2)
 
 
以上Fabric配置,實現的目的是:
簡單的在本地啓動nginx服務器, 在linux1和linux2上啓動了tomcat服務器, 爲了接受nginx服務器的代理,這裏專門使用分組的方式爲了適應機器比較多的集羣的須要;
另外這裏沒有設置服務器的密碼,一是爲了服務器的安全;而是集羣間建議設置ssh免密登陸,腳本就不用設置密碼了;
方法doworks執行的就是最終彙總的任務;
 
開始執行
[root@kevin ~]# fab -f fabric.py doworks

4) fabfile全局屬性 (env對象) nginx

fabfile之env對象的做用是定義fabfile的全局設定,支持多個屬性,包含目標主機、用戶名、密碼、等角色.
env各屬性說明以下:
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.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組主機區分開來;

好比
[root@kevin ~]# vim fabfile.py
..........
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'
}

[root@kevin ~]# vim fabfile.py
..........
env.roledefs = {
    'webservers':['192.168.56.131','192.168.56.132','192.168.56.133'],
    'dbserver':['192.168.56.134','192.168.56.135']
}

env.roledefs的使用方法實例:
[root@kevin ~]# vim fabfile.py
..........
env.roledefs = {'webserver':['192.168.1.21','192.168.1.22'],'dbserver':['192.168.1.25','192.168.1.26']}
#引用分組時使用python裝飾器方式來進行,如:
@roles('webserver')
def webtask():
    run('/usr/local/nginx/sbin/nginx')

@roles('webserver','dbserver')
def publictask():
    run('uptime')


引用時使用Python修飾符的形式進行,角色修飾符下面的任務函數爲其做用域,下面來看一個示例:
[root@kevin ~]# vim fabfile.py
..........
@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就能夠實現不一樣角色執行不一樣的任務函數了。

5) Fabric經常使用APIc++

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) Fabric應用示例說明 git

示例一:  查看本地和遠程主機信息程序員

查看本地信息
本示例調用local()方法執行本地(主控端)命令,添加"@runs_once"修飾符保證該任務函數只執行一次。調用run()方法執行遠程命令。
[root@kevin ~]# vim fabric1.1.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任務函數運行結果以下:
[root@kevin ~]# fab -f fabric1.1.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.


查看遠程主機信息
[root@kevin ~]# vim fabric1.2.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任務函數運行結果以下:
[root@kevin ~]# fab -f fabric1.2.py local_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.


若是將上面兩個文件的需求, 放在一塊兒
[root@kevin ~]# vim fabric1.py
#!/usr/bin/env python
# -*- encoding: utf-8 -*-

from fabric.api import *

env.user = 'root'
env.hosts = ['192.168.1.22']
env.password = '123456'

@runs_once   #查看本地系統信息,當有多臺主機時只運行一次
def local_task():   #本地任務函數
    local('uname -a')
    
def remote_task():
    with cd('/var/logs'):   #with的做用是讓後面的表達式語句繼承當前狀態,實現:cd /var/logs  && ls -l的效果
        run('ls -l')


[root@kevin ~]# fab -f fabric1.py local_task
[root@kevin ~]# fab -f fabric1.py remote_task

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

本示例使用"@task'修復符標誌入口函數go()對外部可見,配合"@runs_once"修飾符接受用戶輸入,最後調用worktask()任務函數實現遠程命令執行。
[root@kevin ~]# vim fabric2.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修復符來達到此目的。

執行結果以下:
[root@kevin ~]# fab -f fabric2.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.

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

本示例經過Fabric的env對象定義網關模式,即俗稱的中轉、堡壘機環境。定義格式爲"env.gateway='192.168.56.11'",其中IP「192.168.56.11」爲堡壘機IP,
再結合任務韓素實現目標主機文件上傳與執行的操做。
[root@kevin ~]# vim fabric3.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()


以下命令運行結果, 默認爲串行運行
[root@kevin ~]# fab -f fabric3.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.


再以下運行結果, 加P參數爲異步並行執行結果
[root@kevin ~]# fab -Pf fabric3.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:

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

咱們時常作一些文件包分發的工做,實施步驟通常是先壓縮打包,在批量上傳至目標服務器,最後作一致性校驗。
本示例經過put()方法實現文件的上傳,經過對比本地與遠程主機文件的md5,最終實現文件一致性校驗。
[root@kevin ~]# vim fabric4.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()


執行命令, 運行結果以下:(提示此程序不支持-P參數並行執行、如需並行執行,程序須要作調整). 若是隻打包, 則"fab -f fabric4.py tar_task", 若是隻上傳, 則"fab -f fabric4.py put_task"
[root@kevin ~]# fab -f fabric4.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')"修復符綁定到對應的任務函數,實現不一樣角色主機的部署差別。
[root@kevin ~]# vim fabric5.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)


執行命令,結果以下:
[root@kevin ~]# fab -Pf fabric5.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.

示例六:  分享一個生產環境代碼包發佈管理的配置

程序生產環境的發佈是業務上線的最後一個環境,要求具有源碼打包、發佈、切換、回滾、版本管理等功能。
本示例實現了這一套流程功能,其中版本切換與回滾使用了Linux下的軟連接實現。
[root@kevin ~]# vim fabric6.py
#!/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軟連接作切換,管理員的版本發佈、回滾操做用戶無感知。
[root@kevin ~]# fab -f fabric6.py go 

示例七: 分享一個自動化部署 Django 項目的配置

[root@kevin ~]# vim fabric7.py
# -*- coding: utf-8 -*-
# 文件名要保存爲 fabfile.py
 
from __future__ import unicode_literals
from fabric.api import *
 
# 登陸用戶和主機名:
env.user = 'root'
# 若是沒有設置,在須要登陸的時候,fabric 會提示輸入
env.password = 'youpassword'
# 若是有多個主機,fabric會自動依次部署
env.hosts = ['www.example.com']
 
TAR_FILE_NAME = 'deploy.tar.gz'
 
def pack():
            """
            定義一個pack任務, 打一個tar包
            :return:
            """
            tar_files = ['*.py', 'static/*', 'templates/*', 'vue_app/', '*/*.py', 'requirements.txt']
            exclude_files = ['fabfile.py', 'deploy/*', '*.tar.gz', '.DS_Store', '*/.DS_Store',
                                                             '*/.*.py', '__pycache__/*']
            exclude_files = ['--exclude=\'%s\'' % t for t in exclude_files]
            local('rm -f %s' % TAR_FILE_NAME)
            
            local('tar -czvf %s %s %s' % (TAR_FILE_NAME, ' '.join(exclude_files), ' '.join(tar_files)))
            print('在當前目錄建立一個打包文件: %s' % TAR_FILE_NAME)
 
 
def deploy():
            """
            定義一個部署任務
            :return:
            """
            # 先進行打包
            pack()
 
            # 遠程服務器的臨時文件
            remote_tmp_tar = '/tmp/%s' % TAR_FILE_NAME
            run('rm -f %s' % remote_tmp_tar)
            # 上傳tar文件至遠程服務器, local_path, remote_path
            put(TAR_FILE_NAME, remote_tmp_tar)
            # 解壓
            remote_dist_base_dir = '/home/python/django_app'
            # 若是不存在, 則建立文件夾
            run('mkdir -p %s' % remote_dist_dir)
 
 # cd 命令將遠程主機的工做目錄切換到指定目錄 
            with cd(remote_dist_dir):
                        print('解壓文件到到目錄: %s' % remote_dist_dir)
                        run('tar -xzvf %s' % remote_tmp_tar)
                        print('安裝 requirements.txt 中的依賴包')
                        # 我使用的是 python3 來開發
                        run('pip3 install -r requirements.txt')
                        remote_settings_file = '%s/django_app/settings.py' % remote_dist_dir
                        settings_file = 'deploy/settings.py' % name
                        print('上傳 settings.py 文件 %s' % settings_file)
                        put(settings_file, remote_settings_file)
 
                        nginx_file = 'deploy/django_app.conf'
                        remote_nginx_file = '/etc/nginx/conf.d/django_app.conf'
                        print('上傳 nginx 配置文件 %s' % nginx_file)
                        put(nginx_file, remote_nginx_file)
            
 # 在當前目錄的子目錄 deploy 中的 supervisor 配置文件上傳至服務器
            supervisor_file = 'deploy/django_app.ini'
            remote_supervisor_file = '/etc/supervisord.d/django_app.ini'
            print('上傳 supervisor 配置文件 %s' % supervisor_file)
            put(supervisor_file, remote_supervisor_file)
            
 # 從新加載 nginx 的配置文件
            run('nginx -s reload')
            run('nginx -t')
            # 刪除本地的打包文件
            local('rm -f %s' % TAR_FILE_NAME)
            # 載入最新的配置文件,中止原有進程並按新的配置啓動全部進程
            run('supervisorctl reload')
            # 執行 restart all,start 或者 stop fabric 都會提示錯誤,而後停止運行
            # 可是服務器上查看日誌,supervisor 有重啓
            # run('supervisorctl restart all')


執行 pack 任務
[root@kevin ~]# fab -f fabric7.py pack

執行 deploy 任務
[root@kevin ~]# fab -f fabric7.py deploy

示例八:  代碼的自動化部署

[root@kevin ~]# vim fabric8.py
#coding=utf-8
from fabric.api import local, abort, settings, env, cd, run
from fabric.colors import *
from fabric.contrib.console import confirm
 
env.hosts = ["root@115.28.×××××"]
env.password = "×××××"
 
 
def get_git_status():
  git_status_result = local("git status", capture=True)
  if "無文件要提交,乾淨的工做區" not in git_status_result:
    print red("****當前分支還有文件沒有提交")
    print git_status_result
    abort("****已經終止")
 
 
def local_unit_test():
  with settings(warn_only=True):
    test_result = local("python manage.py test")
    if test_result.failed:
      print test_result
      if not confirm(red("****單元測試失敗,是否繼續?")):
        abort("****已經終止")
 
 
def server_unit_test():
  with settings(warn_only=True):
    test_result = run("python manage.py test")
    if test_result.failed:
      print test_result
      if not confirm(red("****單元測試失敗,是否繼續?")):
        abort("****已經終止")
 
 
def upload_code():
  local("git push origin dev")
  print green("****代碼上傳成功")
 
 
def deploy_at_server():
  print green("****ssh到服務器進行下列操做")
  with cd("/var/www/××××××"):
    #print run("pwd")
    print green("****將在遠程倉庫下載代碼")
    run("git checkout dev")
    get_git_status()
    run("git pull origin dev")
    print green("****將在服務器上運行單元測試")
    server_unit_test()
    run("service apache2 restart", pty=False)
    print green("****重啓apache2成功")
    print green("********代碼部署成功********")
 
 
def deploy():
  get_git_status()
  local("git checkout dev", capture=False)
  print green("****切換到dev分支")
  get_git_status()
  print green("****將開始運行單元測試")
  local_unit_test()
  print green("****單元測試完成,開始上傳代碼")
  upload_code()
  deploy_at_server()


fabric能夠將自動化部署或者多機操做的命令固化到一個腳本里,從而減小手動的操做。上面是今天第一次接觸這東西后寫的,確實很實用。
運行
[root@kevin ~]# fab -ff abric8.py deploy

主要邏輯就是將本地的dev分支跑單元測試,而後提交到服務器,ssh登錄到服務器,而後pull下來,再跑單元測試,而後重啓apache2。
這個寫的仍是比較簡單的。

===============這裏貼出以前線上環境使用過的一個Fabric自動化配置===============

1) 經過Fabric配置的自動化python上線腳本(包括回滾腳本):
[work@qd-op-zhongkong op]$ cat xcspam-celery.py
from fabric.api import *
from fabric.context_managers import *
import datetime


env.hosts=['qd-vpc-op-rule01']

def antiwater():
    with cd('/app/release'):
        date=datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        repo='http://git.kevinweb.com/zuiyou_server/xcspam.git';
        run('git clone --depth=1 %s' % repo)
        newNmae="xcspam"+"-"+date
        run('mv xcspam %s ' % newNmae)

    with cd('/app/web/xcspam'):
        newRelease=run('ls /app/release/ |tail -1f')
        run('cp -rp /app/release/%s /app/web/xcspam/ ' % newRelease)
        run('unlink bin')
        run('ln -sn %s bin' % newRelease)

    run('superctl restart antiwater:*')

def rollantiwater():
    with cd('/app/web/xcspam'):
        lastrelease=run('ls -rtd xcspam* |tail -2 |head -1')
        run('unlink bin')
        run('ln -sn %s bin' % lastrelease)

    run('superctl restart antiwater:*')

def report():
    with cd('/app/release'):
        date=datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        repo='http://git.kevinweb.com/zuiyou_server/xcspam.git';
        run('git clone --depth=1 %s' % repo)
        newNmae="xcspam"+"-"+date
        run('mv xcspam %s ' % newNmae)

    with cd('/app/web/xcspam'):
        newRelease=run('ls /app/release/ |tail -1f')
        run('cp -rp /app/release/%s /app/web/xcspam/ ' % newRelease)
        run('unlink bin')
        run('ln -sn %s bin' % newRelease)

    run('superctl restart report')

def rollreport():
    with cd('/app/web/xcspam'):
        lastrelease=run('ls -rtd xcspam* |tail -2 |head -1')
        run('unlink bin')
        run('ln -sn %s bin' % lastrelease)

    run('superctl restart report')

def chat():
    with cd('/app/release'):
        date=datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        repo='http://git.kevinweb.com/zuiyou_server/xcspam.git';
        run('git clone --depth=1 %s' % repo)
        newNmae="xcspam"+"-"+date
        run('mv xcspam %s ' % newNmae)

    with cd('/app/web/xcspam'):
        newRelease=run('ls /app/release/ |tail -1f')
        run('cp -rp /app/release/%s /app/web/xcspam/ ' % newRelease)
        run('unlink bin')
        run('ln -sn %s bin' % newRelease)

    run('superctl restart chat')

def rollchat():
    with cd('/app/web/xcspam'):
        lastrelease=run('ls -rtd xcspam* |tail -2 |head -1')
        run('unlink bin')
        run('ln -sn %s bin' % lastrelease)

    run('superctl restart chat')


能夠在一個腳本中定義多個上線項目,上線的時候能夠選擇,以下(回滾的時候選擇對應的roll便可):
[work@qd-op-zhongkong op]$ fab -f xcspam-celery.py antiwater
[work@qd-op-zhongkong op]$ fab -f xcspam-celery.py report
[work@qd-op-zhongkong op]$ fab -f xcspam-celery.py chat


2) 腳本2,其實跟上面無異:
[work@qd-op-zhongkong op]$ cat xcspam-consumer.py
from fabric.api import *
from fabric.context_managers import *
import datetime


env.hosts=['qd-vpc-op-consumer01','qd-vpc-op-consumer02']

def xcspam():
    with cd('/app/release'):
        date=datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        repo='http://git.kevinweb.com/zuiyou_server/xcspam.git';
        run('git clone --depth=1 %s' % repo)
        newNmae="xcspam"+"-"+date
        run('mv xcspam %s ' % newNmae)

    with cd('/app/web/xcspam'):
        newRelease=run('ls /app/release/ |tail -1f')
        run('cp -rp /app/release/%s /app/web/xcspam/ ' % newRelease)
        run('unlink bin')
        run('ln -sn %s bin' % newRelease)

    run('superctl restart xcspam:*')

def rollxcspam():
    with cd('/app/web/xcspam'):
        lastrelease=run('ls -rtd xcspam* |tail -2 |head -1')
        run('unlink bin')
        run('ln -sn %s bin' % lastrelease)

    run('superctl restart xcspam:*')

def chatxcspam():
    with cd('/app/release'):
        date=datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        repo='http://git.kevinweb.com/zuiyou_server/xcspam.git';
        run('git clone --depth=1 %s' % repo)
        newNmae="xcspam"+"-"+date
        run('mv xcspam %s ' % newNmae)

    with cd('/app/web/xcspam'):
        newRelease=run('ls /app/release/ |tail -1f')
        run('cp -rp /app/release/%s /app/web/xcspam/ ' % newRelease)
        run('unlink bin')
        run('ln -sn %s bin' % newRelease)

    run('superctl restart chatxcspam:*')

def chatxcspam():
    with cd('/app/web/xcspam'):
        lastrelease=run('ls -rtd xcspam* |tail -2 |head -1')
        run('unlink bin')
        run('ln -sn %s bin' % lastrelease)

    run('superctl restart chatxcspam:*’)

3) 腳本3
[work@qd-op-zhongkong op]$ cat xcspam-consumer-all.py
from fabric.api import *
from fabric.context_managers import *
import datetime


env.hosts=['qd-vpc-op-consumer01','qd-vpc-op-consumer02']

def xcspam():
    with cd('/app/release'):
        date=datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        repo='http://git.kevinweb.com/zuiyou_server/xcspam.git';
        run('git clone --depth=1 %s' % repo)
        newNmae="xcspam"+"-"+date
        run('mv xcspam %s ' % newNmae)

    with cd('/app/web/xcspam'):
        newRelease=run('ls /app/release/ |tail -1f')
        run('cp -rp /app/release/%s /app/web/xcspam/ ' % newRelease)
        run('unlink bin')
        run('ln -sn %s bin' % newRelease)

    run('superctl restart xcspam:*')

def rollxcspam():
    with cd('/app/web/xcspam'):
        lastrelease=run('ls -rtd xcspam* |tail -2 |head -1')
        run('unlink bin')
        run('ln -sn %s bin' % lastrelease)

    run('superctl restart xcspam:*')

def chatxcspam():
    with cd('/app/release'):
        date=datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        repo='http://git.kevinweb.com/zuiyou_server/xcspam.git';
        run('git clone --depth=1 %s' % repo)
        newNmae="xcspam"+"-"+date
        run('mv xcspam %s ' % newNmae)

    with cd('/app/web/xcspam'):
        newRelease=run('ls /app/release/ |tail -1f')
        run('cp -rp /app/release/%s /app/web/xcspam/ ' % newRelease)
        run('unlink bin')
        run('ln -sn %s bin' % newRelease)

    run('superctl restart chatxcspam:*')

def chatxcspam():
    with cd('/app/web/xcspam'):
        lastrelease=run('ls -rtd xcspam* |tail -2 |head -1')
        run('unlink bin')
        run('ln -sn %s bin' % lastrelease)

    run('superctl restart chatxcspam:*')


def all():
    with cd('/app/release'):
        date=datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        repo='http://git.kevinweb.com/zuiyou_server/xcspam.git';
        run('git clone --depth=1 %s' % repo)
        newNmae="xcspam"+"-"+date
        run('mv xcspam %s ' % newNmae)

    with cd('/app/web/xcspam'):
        newRelease=run('ls /app/release/ |tail -1f')
        run('cp -rp /app/release/%s /app/web/xcspam/ ' % newRelease)
        run('unlink bin')
        run('ln -sn %s bin' % newRelease)

    run('superctl restart all')

def rollall():
    with cd('/app/web/xcspam'):
        lastrelease=run('ls -rtd xcspam* |tail -2 |head -1')
        run('unlink bin')
        run('ln -sn %s bin' % lastrelease)

    run('superctl restart all')


能夠根據需求去選擇具體對那個項目進行上線,上述腳本定義了兩個項目上線,第三個(all)即表示同時上線兩個項目。
[work@qd-op-zhongkong op]$ fab -f xcspam-consumer-all.py xcspam
[work@qd-op-zhongkong op]$ fab -f xcspam-consumer-all.py chatxcspam
[work@qd-op-zhongkong op]$ fab -f xcspam-consumer-all.py all
相關文章
相關標籤/搜索