摘要:當須要同時管理許多服務器時,若是咱們一臺一臺登錄上去操做會顯得費時又費力。此時咱們能夠用fabric這個包提供的API來編寫python腳本完成服務器集羣的統一管理。python
核心原理:fabric爲主動ssh至主機執行指定操做,而不是在主機上裝agent接收指令。django
1、安裝api
pip install fabric3 ====>能夠把fabric看作是一個軟件,安裝後提供操做系統級命令「fab」,而後這個軟件開放一些API,能夠經過python去調用服務器
2、fab經常使用參數(操做系統級命令「fab」的使用參數)多線程
格式:fab 選項參數運維
經常使用選項參數:ssh
-l:查看目標fab程序可用的函數。(須要和-f結合使用)異步
-f:告訴fab程序去讀取哪一個.py文件函數
-g:指定網關測試
-H:指定須要控制的目標主機,多個主機用「,」隔開
-P:以異步並行方式運行多主機任務,默認爲串行任務。(能夠理解爲多線程執行,默認爲一個線程)
-u:指定主機用戶名
-p:指定主機密碼
例:fab -p 密碼 -H 主機1,主機2 --'命令'
fab -u root -p 密碼 -H '172.20.163.121,172.20.163.126' -- 'ifconfig' ===>執行此命令後會輸出172.20.163.121和172.20.163.126的ifconfig信息
3、fabfile腳本編寫
3.1、普通場景示例(適用於全部服務器的用戶名、密碼、業務類型都一致的狀況)(即:一個程序對應一個集羣):
from fabric.api import * ===>導入fabric
# 全局屬性的設定()
# env爲fabric.api裏面的一個對象,能夠經過操縱它的各個屬性實現對自動化運維程序的全局參數配置,它的屬性包括目標主機ip、用戶、密碼、角色等
# 1、env.host:存放目標主機的列表
env.hosts = ['192.168.1.1', '192.168.1.2']
# 2、env.user:定義用戶名
env.user = 'root'
# 3、env.port:定義端口
env.port = 22
# 4、env.password:定義密碼
env.password = '123456'
@task ===> 若是沒加@roles、@hosts等裝飾器,一旦下面這個函數被執行,則全局env.hosts裏面全部的機器都會運行函數內的命令
def show_net():
run('ifconfig') ===>在遠程主機上執行「ifconfig」命令
if __name__ == '__main__':
execute(show_net) ===>若是不使用execute這個函數去執行show_net,則show_net只能用'root@HK:~# fab -f 文件名.py show_net'的方式執行。用了execute後就能夠用'python3 文件名.py'的方式執行了。
===>執行以上代碼後程序會ssh到'192.168.1.1', '192.168.1.2'這兩臺機器上執行'ifconfig'命令並返回結果
3.2、將不一樣主機進行分組管理場景(適用於被管理服務器密碼、業務類型不相同的狀況):
from fabric.api import * ===>導入fabric
env.user = 'root' ====> 儘管下面針對每臺主機有用戶名信息了,這裏也須要定義一個全局user,不知爲啥(碰到須要不一樣用戶名的狀況下就歇菜了)
# 5、env.passwords:定義多臺主機的用戶名、IP地址、端口、密碼(適用於:一堆服務器的密碼不都同樣的狀況)
env.passwords = {
'root@172.20.163.121:22': '123456', ====>測試發現去掉"root@"和":22"後會報錯
'root@172.20.163.126:22': '123456',
}
# 6、env.gateway:定義網關 ====>適用於經過跳板機(堡壘機)登錄的方式
# env.gateway = '192.168.1.254' ===>因沒有環境,因此先把它注掉,這裏只是說明有這個功能而已
# 7、env.roledefs:定義角色分組(可按業務類型將主機進行分組管理)
env.roledefs = {
'group1': ['172.20.163.121'],
'group2': ['172.20.163.126']
}
@task
@roles('group1', 'group2') ====>這個函數被執行時會在'group1', 'group2'這兩個組成員上生效
def show():
run('uname -a')
@task
@roles('group1') ====>這個函數被執行時會在'group1'個組成員上生效
def show_net():
run('ifconfig')
@task
@roles('group2') ====>這個函數被執行時會在'group2'個組成員上生效
def show_mem():
run('free -m')
if __name__ == '__main__':
execute(show) ===>執行show函數時group1、group2兩個分組內的成員都會執行
execute(show_net) ===>執行show-net函數時只有group1分組內成員執行
execute(show_mem) ===>執行show_mem函數時只有group2分組內成員執行
4、本地與遠程運維經常使用API(本地指運行fabric程序端,遠程指被ssh端)
# 1、local:執行本地命令
語法:local('本地命令')
# 2、lcd:切換到本地目錄
語法:lcd('本地目錄')
例:
def local_cmd():
with lcd(r'C:\Users\Administrator'): ===>切換到C:\Users\Administrator目錄(臨時性,執行完with這個總體後仍然處在原來的路徑)
local('dir') ===>在C:\Users\Administrator路徑下執行'dir'命令
local('dir') ===>執行完with這個總體後再次執行dir發現還處在沒有切換目錄前的路徑
# 3、cd:切換遠程目錄
語法:cd('遠程目錄')
# 4、run:執行遠程命令
語法:run('遠程命令')
例:
def remote_cmd():
with cd(r'/'): ===>切換到/目錄(臨時性,執行完with體仍然處在原來的路徑)
run('pwd') ===>此時執行pwd輸出路徑爲'/'
run('pwd') ===>此時執行pwd輸出路徑爲'/root'
5、put:上傳本地文件到遠程主機
語法:put('本地文件', '遠程目錄')
例:
def upload():
put(r'C:\Users\Administrator\Desktop\django.txt', '/root/111.txt')
6、get:從遠程主機下載文件到本地
語法:get('遠程文件', '本地目錄')
例:
def download():
get('/root/get-pip.py', r'C:\Users\Administrator\Desktop\iiii.py')
7、異常處理和文件校驗
from fabric.api import *
from fabric.contrib.console import confirm
from fabric.colors import * ====>文字顏色庫,包含white()、yellow()、red()、blue()、green()、cyan()、magenta()等函數,將字符串丟進去便可爲字符串上色。例:print(yellow('abc')) ===>此時將輸出黃色的'abc'
def abnormal():
# 異常處理
with settings(warn_only=True):
result = put(r'./222.txt', '/root/abc.txt')
if result.failed and not confirm("put file failed,Continue[Y/N]?"): ===>若是路徑錯誤result.failed將爲真,若是result.failed爲真後彈出交互界面問用戶是否要繼續,若是輸入N,則not 0爲真,則執行abort("Aborting file put task !")
abort("Aborting file put task !")
# 文件校驗
with settings(warn_only=True):
local_md5 = local(r'md5sum ./222.txt', capture=True).split(" ")[0] # capture做用:這個開啓後輸出結果將再也不打印至屏幕,而是將結果賦給local_md5
remote_md5 = run('md5sum /root/abc.txt').split(" ")[0] # run函數不用capture參數,默認既會打印至屏幕,也會賦值給remote_md5
if local_md5 == remote_md5:
print(green('校驗經過'))
else:
print(red('校驗失敗'))
confirm說明:
from fabric.contrib.console import confirm
a = confirm('是否要繼續?') ====>confirm將彈出交互界面:'是否要繼續? [Y/n]' 用戶可輸入Y或N
print(a) =====>若是用戶輸入的是Y,則此處打印True。若是用戶輸入的是N,則此處打印False
五、裝飾器說明:
fab調用裝飾器:@task
若是函數前面加了這個裝飾器就能夠用操做系統級別命令fab直接調用這個函數。若是沒加則沒法用fab直接調用。例:
@task
def remote_cmd():
run('ifconfig')
root@HK:~# fab -f ssh.py remote_cmd ====>若是加了@task則能夠直接這麼用,若是沒加則不能這麼用
並行裝飾器:@parallel
角色裝飾器:@roles(分組名)
@task
@parallel ====>當有多個主機要執行下面函數任務時,加上這個裝飾器就能夠起多個進程並行處理了。
@roles('group1', 'group2') ====>多個分組須要執行下面函數
def remote_cmd():
run('ifconfig')
主機裝飾器:@hosts(主機1,主機2)
@task
@parallel ====>當有多個主機要執行下面函數任務時,加上這個裝飾器就能夠起多個進程並行處理了。
@roles('172.20.163.100', '172.20.163.101') ====>除了分組方法外,也能夠手工指定哪臺主機要執行下面函數。
def remote_cmd():
run('ifconfig')