Fabric是Python的一個模塊,基於SSH提供了豐富的交互接口,能夠用來在本地或遠程機器上自動化的執行Shell命令,很是適合用來作應用的遠程部署及系統維護。php
fabric底層基於paramiko(paramiko是用於ssh鏈接的庫)。java
$ pip install fabric
複製代碼
Fabric默認的腳本文件是fabfile.py
,建立該文件並定義以hello函數:python
def hello():
print("Hello Fabric!")
複製代碼
可使用參數-l
來列出當前fabfile.py
中定義了哪些任務,而後在fabfile.py
目錄下執行命令能夠看到輸出結果:nginx
$ fab -l
Available commands:
hello
$ fab hello
Hello Fabric!
Done.
複製代碼
fabfile.py中每一個函數表明一個任務,任務名即函數名。fab命令用來執行fabfile.py中定義的任務,它必須顯示的指定任務名。web
任務也能夠帶參數,好比咱們將hello函數改成:shell
def hello(name, value):
print("Hello Fabric! %s %s." % (name, value))
複製代碼
此時執行hello任務時須要傳入參數:api
$ fab hello:name=Year,value=2017
複製代碼
fabric默認執行的腳本是fabfile.py
,若是要換腳本文件須要使用-f
指定。好比咱們將hello任務放到script.py
中就要執行:安全
$ fab -f script.py hello:name=Year,value=2017
複製代碼
fabfile.py內容以下:bash
#-*- coding:utf-8 -*-
from fabric.api import local
def taskA():
local('touch fab.out && echo "fabric" >> fab.out')
def taskB():
# capture參數能夠捕獲標準輸出存到變量,默認爲False
output = local('echo "Hello World."', capture=True)
print output
複製代碼
執行任務:服務器
$ fab taskA taskB
複製代碼
Fabric真正強大在於能夠很方便的執行遠程機器上的Shell命令,它基於SSH實現。
#-*- coding:utf-8 -*-
from fabric.api import run, env
# env被稱爲環境字典,用來配置一些運行環境相關的信息
env.hosts = ['192.168.1.100', '192.168.1.101']
env.user = 'user'
env.password = 'passwd'
def taskA():
run('cd /usr/local/webserver/php && ls -l')
run('sudo /usr/local/webserver/nginx/sbin/nginx -t')
複製代碼
env.hosts
是設置機器列表的,也能夠把用戶直接寫到hosts裏:
env.hosts = ['user@192.168.1.100', 'user@192.168.1.101']
複製代碼
若是代碼中沒有設置env.hosts
,也能夠在執行任務時經過-H
參數進行指定:
$ fab -H 192.168.1.100 taskA
複製代碼
環境字典fabric.state.env是做爲全局單例實現的,爲方便使用也包含在fabric.api中。env中的鍵一般也被稱爲環境變量。
幾個經常使用的環境變量以下:
若是對於不一樣的服務器想執行不一樣的任務,上面的程序就作不到了,咱們須要對服務器定義角色:
#-*- coding:utf-8 -*-
from fabric.api import env, roles, run, execute, cd
env.roledefs = {
'dev': ['user1@10.216.224.65', 'user2@10.216.224.66'],
'online': ['user3@45.33.108.82']
}
# host strings必須由username@host:port三部分構成,缺一不可,不然運行時仍是會要求輸入密碼
env.passwords = {
'user1@10.216.224.65:22': 'passwd1',
'user2@10.216.224.66:22': 'passwd2',
'user3@45.33.108.82:22': 'passwd3'
}
@roles('dev')
def taskA():
with cd('/usr/local/webserver'):
run('pwd')
@roles('online')
def taskB():
run('pwd')
def task():
execute(taskA)
execute(taskB)
複製代碼
而後執行task任務便可:
$ fab task
複製代碼
Fabric會在dev機器上執行taskA任務,而後在online機器上執行taskB任務。@roles裝飾器指定了它所裝飾的任務會被哪一個角色的服務器執行。
上面的例子都是將登錄密碼寫到腳本文件裏的,這樣作不安全,推薦的方法是設置SSH KEY自動登錄。登錄本地機器生成KEY:
$ ssh-keygen -t rsa -f ~/.ssh/id_rsa_fabric
複製代碼
生成密鑰對以後將公鑰添加到遠程服務器的~/.ssh/authorized_keys
文件中,就能夠實現自動登錄了。
#-*- coding:utf-8 -*-
from fabric.api import env, roles, run, execute, cd
env.hosts = ['10.216.224.65', '10.216.224.66']
env.user = 'user'
env.key_filename = '~/.ssh/id_rsa_fabric'
def taskA():
with cd('/usr/local/webserver'):
run('pwd')
複製代碼
authorized_keys文件權限只全部者可寫,其餘用戶均無寫權限,不然sshd將認爲不安全不容許使用該文件致使還須要輸入密碼認證。
Fabric的上下文管理器是一系列與Python的with語句配合使用的方法,它能夠在with語句塊內設置當前工做環境的上下文。
#-*- coding:utf-8 -*-
from fabric.api import env, lcd, local, cd, path, settings, shell_env, prefix, sudo, run
env.hosts = ['10.216.224.66']
env.user = 'user'
env.key_filename = '~/.ssh/id_rsa_fabric'
def task():
# 設置本地工做目錄
with lcd('/usr/local/webserver'):
local('touch local.out')
# 設置遠程機器的工做目錄
# sudo功能相似run方法,以超級用戶權限執行遠程命令
with cd('/usr/local/webserver'):
sudo('touch remote.out')
# 添加遠程機器的path路徑
# 出了with語句path又回到原來的值
with path('/usr/local/webserver'):
run('echo $PATH')
run('echo $PATH')
# 設置Fabric環境變量參數
# fabric.api.env
# warn_only設置爲True,遇到錯誤不會退出
with settings(warn_only=True):
run('echo $USER')
# shell_env能夠用來臨時設置遠程和本機上的Shell環境變量
with shell_env(JAVA_HOME='/opt/java'):
run('echo $JAVA_HOME')
local('echo $JAVA_HOME')
# 設置命令執行前綴,等同於 run('echo Hi && pwd')
with prefix('echo Hi'):
run('pwd')
local('pwd')
複製代碼
默認狀況下,Fabric在任務遇到錯誤時就會退出,若是咱們但願捕獲這個錯誤而不是退出任務的話,就要開啓warn_only參數。在上面介紹settings()上下文管理器時,咱們已經看到了臨時開啓warn_only的方法了,若是要全局開啓,有兩個方法:
$ fab -w task
複製代碼
#-*- coding:utf-8 -*-
from fabric.api import env
env.warn_only = True
複製代碼
如今遇到錯誤時,控制檯會打出一個警告信息,而後繼續執行後續任務。那咱們怎麼捕獲錯誤並處理呢?像local/run/sudo/get/put等函數都有返回值,當返回值的succeeded屬性爲True時,說明執行成功,反之就是失敗;也能夠檢查返回值的failed屬性,爲True表示執行失敗,有錯誤發生。
#-*- coding:utf-8 -*-
from fabric.api import env, local, cd, put
env.hosts = ['10.216.224.66']
env.user = 'liuzhen'
env.key_filename = '~/.ssh/id_rsa_fabric'
env.warn_only=True
def task():
with cd('/data/server'):
local('touch /data/server/README.md')
upload = put('/data/server/README.md', 'README.md')
if upload.failed:
put('/data/server/README.md', 'README.md', use_sudo=True)
複製代碼
Fabric在多臺機器上執行任務時默認狀況下是串行的。Fabric支持在多臺服務器上並行執行任務,並行能夠有效的加快執行速度。開啓並行執行有以下兩個方法:
$ fab -P task
複製代碼
#-*- coding:utf-8 -*-
from fabric.api import env
env.parallel = True
複製代碼
以上是對任務並行作一個全局控制。若是隻想對某一個任務作並行的話,咱們能夠在任務函數上加上@parallel裝飾器,這樣即使全局並行未開啓,被@parallel裝飾的任務也會並行執行:
#-*- coding:utf-8 -*-
from fabric.api import env, run, parallel
env.hosts = ['10.216.224.65', '10.216.224.66']
env.user = 'user'
env.key_filename = '~/.ssh/id_rsa_fabric'
@parallel
def taskA():
run('echo "parallel"')
def taskB():
run('echo "serial"')
複製代碼
假如全局並行已開啓,咱們想讓某個任務串行執行,咱們能夠在任務函數上加上@serial裝飾器,這樣即使並行已開啓,被@serial裝飾的任務也會串行執行:
#-*- coding:utf-8 -*-
from fabric.api import env, run, serial
env.hosts = ['10.216.224.65', '10.216.224.66']
env.user = 'user'
env.key_filename = '~/.ssh/id_rsa_fabric'
env.parallel = True
def taskA():
run('echo "parallel"')
@serial
def taskB():
run('echo "serial"')
複製代碼
Fabric常規用法這裏就基本介紹完了,詳細的能夠參考官方文檔。