Python模塊學習 - fabric

簡介

fabric是一個Python的庫,同時它也是一個命令行工具。使用fabric提供的命令行工具,能夠很方便地執行應用部署和系統管理等操做。html

fabric依賴於paramiko進行ssh交互,fabric的設計思路是經過幾個API接口來完成全部的部署,所以fabric對系統管理操做進行了簡單的封裝,好比執行命令,上傳文件,並行操做和異常處理等。python

#安裝
# fabric3支持python3
pip3 install fabric3

因爲fabric比較特殊它仍是一個命令行工具,能夠經過help進行命令的瞭解mysql

pyvip@Vip:~/utils$ fab --help
Usage: fab [options] <command>[:arg1,arg2=val2,host=foo,hosts='h1;h2',...] ...

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
……

錯誤的提示linux

# fab -help
Traceback (most recent call last):
  File "/usr/local/python3/bin/fab", line 11, in <module>
    load_entry_point('Fabric==1.14.0', 'console_scripts', 'fab')()
  File "/usr/local/python3/lib/python3.6/site-packages/pkg_resources/__init__.py", line 480, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/usr/local/python3/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2693, in load_entry_point
    return ep.load()
  File "/usr/local/python3/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2324, in load
    return self.resolve()
  File "/usr/local/python3/lib/python3.6/site-packages/pkg_resources/__init__.py", line 2330, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
  File "/usr/local/python3/lib/python3.6/site-packages/fabric/main.py", line 13, in <module>
    from operator import isMappingType
ImportError: cannot import name 'isMappingType'

# 說明你使用的python版本可fabric版本不一樣,python3 安裝時使用的是fabric3

  

入門使用

fabric的典型使用方式就是,建立一個Python文件,該文件包含一到多個函數,而後使用fab命令調用這些函數。這些函數在fabric中成爲task,下面是一個例子web

from fabric.api import *
from fabric.contrib.console import confirm
from fabric.utils import abort
from fabric.colors import *

env.hosts = ['192.168.5.128']
env.port = 22
env.user = 'root'
env.password = 'mysql123'


def hostname():
    run('hostname')


def ls(path='.'):
    run('ls {0}'.format(path))


def tail(path='/etc/pas', line=10):
    run('tail -n {0} {1}'.format(line, path))


def hello():
    with settings(hide('everything'),warn_only=True):   # 關閉顯示
        result = run('anetstat -lntup|grep -w 25')
        print(result)                                   # 命令執行的結果
        print(result.return_code)                       # 返回碼,0表示正確執行,1表示錯誤
        print(result.failed)

  

PS:fab命令執行時,默認引用一個名爲fabfile.py的文件,咱們也能夠經過-f來進行指定(文件名不能爲abc.py,會衝突).redis

這裏使用了三個fabric的封裝:sql

  1. run:用於執行遠程命令的封裝
  2. sudo:以sudo權限執行遠程命令
  3. env:保存用戶配置的字典(保存了相關的配置,好比登陸用戶名env.user,密碼env.password,端口env.port等,若是沒有指定用戶名那麼默認使用當前用戶,端口使用22)
 一、獲取任務列表
pyvip@Vip:~/utils$ fab -f fab_utils.py --list
Available commands:

    hello
    hostname
    ls
    tail

pyvip@Vip:~/utils$ fab -f fab_utils.py --list
Available commands:

    hello
    hostname
    ls
    tail
# 二、執行hostname函數
pyvip@Vip:~/utils$ fab -f fab_utils.py hostname
[192.168.5.128] Executing task 'hostname'
[192.168.5.128] run: hostname
[192.168.5.128] out: china
[192.168.5.128] out: 


Done.
Disconnecting from 192.168.5.128... done.
# 三、多個參數的狀況
pyvip@Vip:~/utils$ fab -f fab_utils.py ls:/
[192.168.5.128] Executing task 'ls'
[192.168.5.128] run: ls /
[192.168.5.128] out: bin  boot  data  dev  etc  home  lib  lib64  lost+found  media	misc  mnt  net	opt  proc  root  sbin  selinux	srv  sys  tmp  usr  var
[192.168.5.128] out: 


Done.
Disconnecting from 192.168.5.128... done.

須要注意的是:shell

  • 一次能夠多個task,按照順序執行: fab -f fab_util.py hostname ls
  • 給task傳遞參數使用task:參數,多個參數按照位置進行傳遞(和Python相同,對於關鍵字的參數能夠,在命令行中指定:fab ls:path=/home)

fabric的命令行參數

fab命令做爲fabric程序的入口提供了,豐富的參數調用.json

# -l:查看task列表

# -f:指定fab的入口文件,默認是fabfile.py
# -g:指定網管設備,好比堡壘機環境下,填寫堡壘機的IP
# -H:在命令行指定目標服務器,用逗號分隔多個服務器
# -P:以並行方式運行任務,默認爲串行
# -R:以角色區分不一樣的服務
# -t:鏈接超時的時間,以秒爲單位
# -w:命令執行失敗時的警告,默認是終止任務
# -- Fabric參數,其餘包含fabric腳本的中的參數的快捷操做,好比--user,--port,或者直接跟要執行的Linux命令

  以下例子,不寫一行代碼獲取全部主機的ip地址api

pyvip@Vip:~/utils$ fab -H 192.168.5.128 --port 22 --user='root' --password='mysql123' -- 'ip a '
[192.168.5.128] Executing task '<remainder>'
[192.168.5.128] run: ip a 
[192.168.5.128] out: 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
[192.168.5.128] out:     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
[192.168.5.128] out:     inet 127.0.0.1/8 scope host lo
[192.168.5.128] out:     inet6 ::1/128 scope host 
[192.168.5.128] out:        valid_lft forever preferred_lft forever
[192.168.5.128] out: 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
[192.168.5.128] out:     link/ether 00:0c:29:96:0a:a0 brd ff:ff:ff:ff:ff:ff
[192.168.5.128] out:     inet 192.168.5.128/24 brd 192.168.5.255 scope global eth0
[192.168.5.128] out:     inet6 fe80::20c:29ff:fe96:aa0/64 scope link 
[192.168.5.128] out:        valid_lft forever preferred_lft forever
[192.168.5.128] out: 3: pan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN 
[192.168.5.128] out:     link/ether 7a:4d:51:6c:c2:cd brd ff:ff:ff:ff:ff:ff

 

經常使用的對象和方法介紹 

介紹fabric中的env對象,以及其餘的好比執行命令模塊,上傳文件等。

fabric中的env

 env是一個全局惟一的字典,保存了Fabric全部的配置,在Fabric的實現中,他是一個_AttributeDict()對象,之因此封裝成_AttributeDict()對象,是覆蓋了__getattr__和__setattr__,使咱們可使用「對象.屬性=值」的方式,操做字典。

 咱們能夠經過源碼的方式,查看env的配置參數,或者使用以下方式查看:

import json
from fabric.api import env

print(json.dumps(env, indent=3))


def hell(name='world'):
    print('hello %s' % name)


-----------------------------------------------
結果


pyvip@Vip:~/utils$ fab -f fab_utils.py -l
{
   "show": null,
   "": true,
   "sudo_user": null,
   "default_port": "22",
   "key_filename": null,
   "path": "",
   "hosts": [
      "192.168.5.128"
   ],
   "host_string": null,
   "ok_ret_codes": [
      0
   ],
   "always_use_pty": true,
   "fabfile": "fab_utils.py",
   "echo_stdin": true,
   "again_prompt": "Sorry, try again.",
   "command": null,
   "forward_agent": false,
   "command_prefixes": [],
   "cwd": "",
   "connection_attempts": 1,
   "linewise": false,
   "gateway": null,
   "use_exceptions_for": {
      "network": false
……

 

經常使用的env配置以下:

  • env.hosts:定義目標服務器列表
  • env.exclude_hosts:排除特定的服務器
  • env.user SSH:到遠程服務器的用戶名
  • env.port:遠程服務器的端口號
  • env.key_filename:私鑰文件的位置
  • env.password SSH:到遠程服務器的密碼

針對不一樣主機不一樣密碼的狀況,可使用以下的方式:

env.hosts = [
    'root@192.168.10.201:22',
    'root@192.168.10.202:22',
    'root@192.168.10.203:22'
]
env.passwords = {
    'root@192.168.10.201:22':'123456201',
    'root@192.168.10.202:22':'123456202',
    'root@192.168.10.203:22':'123456203'

  

fabric提供的命令

run():在遠程服務器上執行Linux命令,還有一個重要的參數pty,若是咱們執行命令之後須要有一個常駐的服務進程,那麼就須要設置pty=False,避免由於Fabric退出致使進程的退出

run('service mysqld start',pty=False)

 PS:執行完畢會返回輸出的信息,咱們能夠定義變量接受,同時這個返回信息有一個方法return_code,當返回的是正確執行的結果時code爲0,不然不爲0

def hello():

    with settings(hide('everything'),warn_only=True):   # 關閉顯示
        result = run('anetstat -lntup|grep -w 25')
        print(result)                                   # 命令執行的結果
        print(result.return_code)                       # 返回碼,0表示正確執行,1表示錯誤

結果

[192.168.5.128] Executing task 'hello'
/bin/bash: anetstat: command not found
1
True

Done.
Disconnecting from 192.168.5.128... done.

sudo():與run相似,使用管理員權限在遠程服務器上執行shell命令,還有一個重要的參數pty,若是咱們執行命令之後須要有一個常駐的服務進程,那麼就須要設置pty=False,避免由於Fabric退出致使進程的退出。

local():用以執行本地命令,返回要執行的命令,local是對Python的Subprocess模塊的封裝,更負載的功能能夠直接使用Subprocess模塊,包含capture參數,默認爲False,表示subprocess輸出的信息進行顯示,若是不想顯示,那麼指定capture=True便可

 

ef test():
    result = local('make test',capture=True)
    print(result)
    print(result.failed)
    print(result.succeeded)
 
# 返回執行的命令
# 若是執行失敗那麼 result.failed 爲True
# 若是執行成功那麼 result.succeeded 爲True

get():從遠程服務器上獲取文件,經過remote_path參數聲明從何處下載,經過local_path表示下載到何處。remote_path支持通配符。

get(remote_path='/etc/passwd',local_path='/tmp/passwd')

put():將本地的文件上傳到遠程服務器,參數與get類似,此外,還能夠經過mode參數執行遠程文件的權限配置。

get(remote_path='/etc/passwd',local_path='/tmp/passwd')

  

reboot():重啓遠程服務器,能夠經過wait參數設置等待幾秒鐘重啓

	
reboot(wait=30)

propmt():用以在Fabric執行任務的過程當中與管理員進行交互,相似於python的input

key = prompt('Please specify process nice level:',key='nice',validate=int)
# 會返回採集到的key

  

fabric的上下文管理器

env中存儲的是全局配置,有時候咱們並不但願修改全局配置參數,只但願臨時修改部分配置,例如:修改當前工做目錄,修改日誌輸出級別等。

在fabric中咱們能夠經過上下文管理器臨時修改參數配置,而不會影響全局配置。當程序進入上下文管理器的做用域時,臨時修改就會起做用;當程序離開上下文管理器時,臨時修改就會消失。

cd():切換遠程目錄

def change(dir='/tmp'):
    with cd(dir):
        run('pwd')     # /tmp
    run('pwd')         # /root

lcd():切換本地目錄

path():配置遠程服務器PATH環境變量,只對當前會話有效,不會影響遠程服務器的其餘操做,path的修改支持多種模式

  • append:默認行爲,將給定的路徑添加到PATH後面。
  • prepend:將給定的路徑添加到PATH的前面。
  • replace:替換當前環境的PATH變量。
def addpath():
    with path('/tmp','prepend'):
        run("echo $PATH")
    run("echo $PATH")

prefix():前綴,它接受一個命令做爲參數,表示在其內部執行的代碼塊,都要先執行prefix的命令參數。

def testprefix():
    with cd('/tmp'):
        with prefix('echo 123'):
            run('echo 456')
            run('echo 789')
 
# 轉換爲Linux命令爲:
cd /tmp && echo '123' && echo '456'
cd /tmp && echo '123' && echo '789' 

shell_env():設置shell腳本的環境變量 

def setenv():
    with shell_env(HTTP_PROXY='1.1.1.1'):
        run('echo $HTTP_PROXY')
    run('echo $HTTP_PROXY')
 
# 等同於shell中的export
export HTTP_PROXY='1.1.1.1'

settings():通用配置,用於臨時覆蓋env變量

def who():
    with settings(user='dev'):    # 臨時修改用戶名爲dev
        run('who')
    run('who')

 

remote_tunnel():經過SSH的端口轉發創建的連接

with remote_tunnel(3306):
    run('mysql -uroot -p password')

  

hide():用於隱藏指定類型的輸出信息,hide定義的可選類型有7種

  • status:狀態信息,如服務器斷開連接,用戶使用ctrl+C等,若是Fabric順利執行,不會有狀態信息
  • aborts:終止信息,通常將fabric看成庫使用的時候須要關閉
  • warnings:警告信息,如grep的字符串不在文件中
  • running:fabric運行過程當中的數據
  • stdout:執行shell命令的標準輸出
  • stderr:執行shell命令的錯誤輸出
  • user:用戶輸出,相似於Python中的print函數

爲了方便使用,fabric對以上其中類型作了進一步的封裝

  • output:包含stdout,stderr
  • everything:包含stdout,stderr,warnings,running,user
  • commands:包含stdout,running

show():與hide相反,表示顯示指定類型的輸出

def hello():
    with settings(show('everything'),warn_only=True):   # 顯示全部
        result = run('netstat -lntup|grep')
        print('1='+result)                                   # 命令執行的結果
        print('2='+str(result.return_code))                  # 返回碼,0表示正確執行,1表示錯誤
        print('3='+str(result.failed))

結果

pyvip@Vip:~/utils$ fab -f fab_utils.py hello
[192.168.5.128] Executing task 'hello'
[192.168.5.128] run: netstat -lntup|grep
[192.168.5.128] out: 用法: grep [選項]... PATTERN [FILE]...
[192.168.5.128] out: 試用‘grep --help’來得到更多信息。
[192.168.5.128] out: 


Warning: run() received nonzero return code 2 while executing 'netstat -lntup|grep'!

NoneType


1=用法: grep [選項]... PATTERN [FILE]...
試用‘grep --help’來得到更多信息。
2=2
3=True

Done.

 

quiet():隱藏所有輸出,僅在執行錯誤的時候發出告警信息,功能等同於 with settings(hide('everything'),warn_only=True) .

# 好比建立目錄的時候,若是目錄存在,默認狀況下Fabric會報錯退出,咱們是容許這種錯誤的,因此針對這種錯誤,咱們進行以下設置,使fabric只打出告警信息而不會中斷執行。
with settings(warn_only=True)

  

裝飾器

Fabric提供的命令通常都是執行某一個具體的操做,提供的上下文管理器通常都是用於臨時修改配置參數,而fabric提供的裝飾器,既不是執行具體的操做,也不是修改參數,而是控制如何執行這些操做,在那些服務器上執行這些操做,fabric的裝飾器與人物執行緊密相關。下面從幾個方面來進行說明

  • hosts:定製執行task的服務器列表
  • roles:定義執行task的role列表
  • parallel:並行執行task
  • serial:串行執行task
  • task:定義一個task
  • runs_once:該task只執行一次

fabric的task

 

task就是fabric須要在遠程服務器上執行的函數,在fabric中有3中方法定義一個task

  1. 默認狀況下,fabfile中每個函數都是一個task。
  2. 繼承自fabric的task類,這種方式比較難用,不推薦。
  3. 使用fabric的task裝飾器,這是使用fabric最快速的方式,也是推薦的用法。
from fabric.api import *
 
env.user='root'
env.password='mysql123'
 
@task
def hello():
    run('echo hello')
 
def world():
    run('echo world')

  PS:默認狀況下,fabfile中的全部函數對象都是一個task,可是若是咱們使用了task裝飾器,顯示的定義了一個task,那麼,其餘沒有經過task裝飾器裝飾的函數將不會被認爲是一個task。

fabric的host

爲了方便咱們的使用,fabric提供了很是靈活的方式指定對哪些遠程服務器執行操做,根據咱們前面的知識,咱們知道有兩種方式:經過env.hosts來執行,或者在fab執行命令的時候使用-H參數,除此以外,還有如下須要注意的地方

  1. 指定host時,能夠同時指定用戶名和端口號: username@hostname:port
  2. 經過命令行指定要多哪些hosts執行人物:fab mytask:hosts="host1;host2"
  3. 經過hosts裝飾器指定要對哪些hosts執行當前task
  4. 經過env.reject_unkown_hosts控制未知host的行爲,默認True,相似於SSH的StrictHostKeyChecking的選項設置爲no,不進行公鑰確認。
from fabric.api import *
 
env.hosts = [
    'root@192.168.10.201:22',
    'root@192.168.10.202:22',
    'root@192.168.10.203:22'
]
env.passwords = {
    'root@192.168.10.201:22':'123456201',
    'root@192.168.10.202:22':'123456202',
     'root@192.168.10.203:22':'123456203'
}
 
@hosts('root@192.168.10.201:22')
@task
def hello():
    run('ifconfig br0')
 
 
# 命令行的方式:
fab hello:hosts="root@192.168.10.201;root@192.168.10.202"

  

fabric的role

role是對服務器進行分類的手段,經過role能夠定義服務器的角色,以便對不一樣的服務器執行不一樣的操做,Role邏輯上將服務器進行了分類,分類之後,咱們能夠對某一類服務器指定一個role名便可。進行task任務時,對role進行控制。

# role在env.roledefs中進行定義
env.roledefs = {
    'web':['root@192.168.10.201','192.168.10.202']    # role名稱爲:web
    'db':['root@192.168.10.203',]                     # role名稱爲:db
}
  當咱們定義好role之後,咱們就能夠經過roles裝飾器來指定在哪些role上運行task。


from fabric.api import *
 
env.roledefs = {
    'web':['root@192.168.10.201:22','root@192.168.10.202:22',],
    'db':['root@192.168.10.203:22',]
}
env.passwords = {
    'root@192.168.10.201:22':'123456201',
    'root@192.168.10.202:22':'123456202',
    'root@192.168.10.203:22':'123456203'
}
 
@roles('db')       # 只對role爲db的主機進行操做
@task
def hello():
    run('ifconfig br0')

 注意:hosts裝飾器能夠和roles裝飾器一塊兒使用(全集),看起來容易形成混亂,不建議混搭。

 

fabric的執行模型

 

fabric執行任務的步驟以下:

  1. 建立任務列表,這些任務就是fab命令行參數指定的任務,fab會保持這些任務的順序
  2. 對於每一個任務,構造須要執行該任務的服務器列表,服務器列表能夠經過命令行參數指定,或者env.hosts指定,或者經過hosts和roles裝飾器指定
  3. 遍歷任務列表,對於每一臺服務器分別執行任務,能夠將任務列表和服務器列表看做是兩個for循環,任務列表是外層循環,服務器列表是內存循環,fabric默認是串行執行的能夠經過裝飾器或者命令行參數肯定任務執行的方式
  4. 對於沒有指定服務器的任務默認爲本地任務,僅執行一次

PS:關於並行模式:

  1. 經過命令行參數-P(--parallel)通知Fabric並行執行task
  2. 經過env.parallel設置設否須要並行執行
  3. 經過parallel裝飾器通知Fabric並行執行task,它接受一個pool_size做爲參數(默認爲0),表示能夠有幾個任務並行執行

其餘裝飾器

前面介紹了task,hosts,roles和parallel裝飾器,此外還有兩個裝飾器比較經常使用

  • runs_once:只執行一次,防止task被屢次調用。例如,對目錄打包進行上傳,上傳動做對不一樣的服務器可能會執行屢次,可是打包的動做只須要執行一次便可。
  • serial:強制當前task穿行執行。使用該參數時優先級最高,即使是制定了併發執行的參數

經常使用的功能函數

fabric中還有其餘的一些好用的函數

封裝task

 fabric提供了一個execute函數,用來對task進行封裝。它最大的好處就是能夠將一個大的任務拆解爲不少小任務,每一個小任務互相獨立,互不干擾

from fabric.api import *
 
env.roledefs = {
    'web':['root@192.168.10.201:22','root@192.168.10.202:22',],
    'db':['root@192.168.10.203:22',]
}
env.passwords = {
    'root@192.168.10.201:22':'123456201',
    'root@192.168.10.202:22':'123456202',
    'root@192.168.10.203:22':'123456203'
}
 
@roles('db')
def hello():
    run('echo hello')
 
@roles('web')
def world():
    run('echo world')
 
@task
def helloworld():
    execute(hello)    
    execute(world)

 # 函數helloworld做爲入口,分別調用兩個task,對不一樣的主機進行操做

 

utils函數

 

包含一些輔助行的功能函數,這些函數位於fabric.utils下,經常使用的函數以下:

  1. abort:終止函數執行,打印錯誤信息到stderr,而且以退出碼1退出。
  2. warn:輸出警告信息,可是不會終止函數的執行
  3. puts:打印輸出,相似於Python中的print函數
def helloworld():
    execute(hello)
    abort('----->abort')     # 執行到這裏時,直接退出
    warn('----->warn')       # 會發出提示信息,不會退出
    puts('----->puts')       # 會打印括號中的信息
    execute(world)

  

帶顏色的輸出 

 fabric爲了讓輸出日誌更具備可讀性,對命令行中斷的顏色輸出進行了封裝,使用print打印帶有不一樣顏色的文本,這些顏色包含在fabric.colors中。像warn,puts打印輸出的,也能夠直接渲染顏色

  • blue(text,blod=False)  藍色
  • cyan(text,blod=False)  淡藍色
  • green(text,blod=False)  綠色
  • magenta(text,blod=False)  紫色
  • red(text,blod=False)  紅色
  • white(text,blod=False)  白色
  • yellow(text,blod=False)   黃色
def ls(path='.'):
    run('ls {0}'.format(path))

def hello():

    execute(hell)  # task任務hell
    warn(yellow('----->warn'))  # 會發出提示信息,不會退出
    puts(green('----->puts'))  # 會打印括號中的信息
    execute(ls) # task任務ls
    print(green('the text is green')) # 單純的渲染文字: 

def hell(name='world'):
    print('hello %s' % name)

 

 

  

確認信息

有時候咱們在某一步執行錯誤,會給用戶提示,是否繼續執行時,confirm就很是有用了,它包含在 fabric.contrib.console中

def testconfirm():

    result = confirm('Continue Anyway?')
    print(result)
 
 
# 會提示輸入y/n
# y 時 result爲True
# n 時 result爲False

  

使用Fabric源碼安裝redis

下載一個redis的包和fabfile.py放在同級目錄便可,不一樣目錄須要修改包的位置,這裏使用的是redis-4.0.9版本。

#!/usr/bin/env python3
from fabric.api import *
from fabric.contrib.console import confirm
from fabric.utils import abort
from fabric.colors import *
 
env.hosts = ['192.168.10.202',]
env.user = 'root'
env.password = '123456202'
 
@runs_once
@task
def test():
    with settings(warn_only=True):
        local('tar xf redis-4.0.9.tar.gz')
        with lcd('redis-4.0.9'):
            result = local('make test',capture=True)
            if result.failed and not confirm('Test is Faild Continue Anyway?'):
                abort('Aborting at user request.')
 
    with lcd('redis-4.0.9'):
        local("make clean")
    local('tar zcvf redis-4.0.10.tar.gz redis-4.0.9')
 
@task
def deploy():
    put('redis-4.0.10.tar.gz','/tmp/')
    with cd('/tmp'):
        run('tar xf redis-4.0.10.tar.gz')
        with cd('redis-4.0.9'):
            sudo('make install')
 
@task
def start_redis():
    with settings(warn_only=True):
        result = run('netstat -lntup | grep -w redis-server')
        if result.return_code == 0:
            print(green('redis is started!'))
        else:
            run('set -m ; /usr/local/bin/redis-server &')   # 用pty=False, fabric進程退不出來,不知道爲啥,因此這裏用set -m
            print(green('redis start Successful'))
 
@task
def clean_local_file():
    local('rm -rf redis-4.0.10.tar.gz')
 
@task
def clean_file():
    with cd('/tmp'):
        sudo('rm -rf redis-4.0.9')
        sudo('rm -rf redis-4.0.10.tar.gz')
 
@task
def install():
    execute(test)
    execute(deploy)
    execute(clean_file)
    execute(clean_local_file)
 execute(start_redis)

  

PS:關於set -m 的做用以下:

"set -m" turns on job control, you can run processes in a separate process group.
理解:在一個獨立的進程組裏面運行咱們的進程。

  參考資料

http://www.cnblogs.com/dachenzi/p/8695330.html

相關文章
相關標籤/搜索