系統批量運維管理器Fabric詳解

xie仗劍天涯發表於2017-08-23
系統批量運維管理器Fabric詳解

Fabrici 是基於python現實的SSH命令列工具,簡化了SSH的應用程式部署及系統管理任務,它提供了系統基礎的操作元件,可以實現本地或遠端shell命令,包括執行,檔案上傳,下載及完整執行的日誌輸出等功能,Fabrici 比 paramiko 的基礎上做了更高層的封裝,操作起來更加簡單。

Fabric安裝

Fabric支援pip,easy_install 或原始碼安裝方式。

pip install fabric
easy_install fabric
Fabric 簡單使用示例

定義一個任務函式,通過run方法實現遠端執行"uname -s"命令

#!/usr/bin/env python
# -*- ending: utf-8 -*-

from fabric.api import run

def host_type():
        run("unmae -s")

[root@cinder01 project]# fab -f fab_run_01.py -H 192.168.165.45 host_type
[192.168.165.45] Executing task 'host_type'
[192.168.165.45] run: uname -s
[192.168.165.45] Login password for 'root': 
[192.168.165.45] out: Linux
[192.168.165.45] out:

解釋: -f 用於指定執行檔案,-H 指定執行主機,host_type為 fab_run_01.py 中的函式名

fab的常用引數介紹

fab 為Fabric程式的命令列入口,提供豐富的引數呼叫,命令格式如下:

fab [options] <command>[:arg1,arg2=var1,host=foo,host2='h1;h2'...] ...

幾個常用引數解釋,更多引數說明可以使用fab -help命令檢視

-l, 顯示定義好的任務函式名
-f, 指定fab入口檔案,預設入口檔名為fabfile.py
-g, 指定閘道器裝置,比如堡壘機環境,指定填寫IP地址即可
-H, 指定目標主機,多臺主機使用“,”號分割
-P, 以非同步並行的方式執行多臺主機任務,預設為序列執行
-R, 指定role(角色),以角色名區分不同業務組裝置
-t, 設定設定連線超時時間(秒)
-T, 設定遠端主機命令執行超時時間(秒) 
-w, 當命令執行失敗,發出警告,而非預設終止任務
fabfile.py檔案的編寫

全域性屬性設定:
env物件的作用是定義fabfile的全域性設定,支援多個屬性,包括目標主機、使用者、密碼、角色等

env.host, 定義目標主機,可以用IP或主機名錶示,以python列表形式定義,例:env.hosts = ["192.168.1.1","192.168.1.2"]
env.exclude_hosts, 排除指定主機,示例:env.exclude_hosts=["192.168.1.2"]
env.user, 定義主機名,如:env.user="root"
env.port, 定義目標主機埠,預設為22,如:env.port="22"
env.password, 定義密碼,如:env.password="123456"
env.passwords, 與password功能一樣,區別在於不同主機不同密碼的應用場景,示例:
    env.passwords = {
        "root@192.168.1.1:22": "123456",
        "root@192.168.1.2:22": "1234567"
    }
env.gateway, 定義閘道器(堡壘機)IP,如:env.gateway="192.168.1.254"
env.deploy_release_dir, 自定義全域性變數,格式:env.+"變數名",如:env.age,env.name
env.roledefs, 定義角色分組,示例:將web和db主機組區分,定義如下:
    env.roledefs = {
        "webservers":["192.168.1.1","192.168.1.2"]
        "dbservers":["192.168.2.1"]
    }
Fabric 常用API

Fabric 提供了一組簡單強大的fabric.api命令集,常用的方法和說明如下:

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/abc.txt','/tmp/abc1.txt');
get, 從遠端主機下載檔案到本地,如:get('/tmp/abc1.txt','/home/abc.txt');
prompt, 獲得使用者輸入資訊,如:prompt('input password:');
confirm, 獲得提示資訊確認,如:confirm("Tests failed. Continue[Y/N]?");
reboot, 重啟遠端主機,如:reboot();
@task, 函式修飾符,標識函式為fab呼叫,非標識fab不可見,純業務邏輯;
@runs_once, 函式修飾符,標識函式只會執行一次,不受多臺主機影響;
Fabric使用簡單示例

示例1:檢視本地與遠端主機資訊

# cat fab_simple1.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from fabric.api import *

env.user = "root"
env.hosts = ["192.168.165.45", "192.168.165.38"]
env.password = "NFjd1234"

@runs_once      #檢視本地系統資訊,當有多臺主機時只執行一次
def local_task():  # 本地任務函式
    local("uname -a")
    local("df -h")

def remote_task():
    with cd("/home"):  # with的作用是讓後面的表示式語句整合當前狀態,效果相對於"cd /home && ls -l"
        run("ls -l")
        
通過fab命令呼叫local_task任務函式執行結果:
# fab -f fab_simple1.py local_task 
[192.168.165.45] Executing task 'local_task'
[localhost] local: uname -a
Linux cinder01 3.10.0-514.2.2.el7.x86_64 #1 SMP Tue Dec 6 23:06:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
[localhost] local: df -h
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   96G  3.6G   92G   4% /
devtmpfs                 1.9G     0  1.9G   0% /dev
tmpfs                    1.9G     0  1.9G   0% /dev/shm
tmpfs                    1.9G   33M  1.9G   2% /run
tmpfs                    1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/sda1                497M  172M  326M  35% /boot
tmpfs                    380M     0  380M   0% /run/user/0

Done.

呼叫remote_task任務函式的執行結果:
# fab -f fab_simple1.py remote_task
[192.168.165.45] Executing task 'remote_task'
[192.168.165.45] run: ls -l
[192.168.165.45] out: total 142448
[192.168.165.45] out: drwxr-xr-x 2 root        root              39 Feb 23 21:00 files
[192.168.165.45] out: -rw-r--r-- 1 root        root            1486 Feb 23 20:27 iperf.sh
[192.168.165.45] out: drwx------ 2 user001     user001           79 Aug 10 16:18 user001
[192.168.165.45] out: 

[192.168.165.38] Executing task 'remote_task'
[192.168.165.38] run: ls -l
[192.168.165.38] out: total 0
[192.168.165.38] out: drwxr-xr-x 13 mysql mysql 245 Feb 25 15:01 mysql
[192.168.165.38] out: 

Done.
Disconnecting from 192.168.165.38... done.
Disconnecting from 192.168.165.45... done.

示例2:動態獲取遠端主機目錄列表

# cat fab_simple2.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from fabric.api import *

env.user = "root"
env.hosts = ["192.168.165.45", "192.168.165.38"]
env.password = "NFjd1234"

@runs_once
def input_raw():
        return prompt("Pleace input dir_name:",default="/home")

def worktask(dirname):
        run("ls -l " + dirname)

@task
def go():
        getdirname = input_raw()
        worktask(getdirname)
        
執行結果:
# fab -f fab_simple2.py go
[192.168.165.45] Executing task 'go'
Pleace input dir_name: [/home] /tmp
[192.168.165.45] run: ls -l /tmp
[192.168.165.45] out: total 65532
[192.168.165.45] out: drwx------  3 root root       16 Aug 10 17:27 systemd-private-07be82ffd072480995e44cf275addead-httpd.service-UnfiFO
[192.168.165.45] out: -r--r--r--. 1 root root 67101758 Dec 20  2016 VMwareTools-9.0.5-1065307.tar.gz
[192.168.165.45] out: drwxr-xr-x. 4 root root       32 Mar 23  2013 vmware-tools-distrib
[192.168.165.45] out: 

[192.168.165.38] Executing task 'go'
[192.168.165.38] run: ls -l /tmp
[192.168.165.38] out: total 0
[192.168.165.38] out: srwxrwxrwx 1 mysql mysql  0 Jul 24 01:10 mysql.sock
[192.168.165.38] out: drwx------ 3 root  root  17 Jul 24 01:10 systemd-private-d4d53ae723f941588677f00dedf44a0a-vmtoolsd.service-fR3ZqE
[192.168.165.38] out: 

Done.
Disconnecting from 192.168.165.38... done.
Disconnecting from 192.168.165.45... done.

示例3: 閘道器模式檔案上傳與執行
通過Fabric的env物件定義閘道器模式,結合任務函式實現目標主機檔案上傳與執行的操作

# cat fab_simple3.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from fabric.api import *
from fabric.context_managers import *
from fabric.contrib.console import confirm

env.user = "root"
env.gateway = "192.168.165.42"   # 定義堡壘機,做檔案上傳,執行的中轉站
env.hosts = ["192.168.165.45", "192.168.165.38"]
env.password = "NFjd1234"

lpackpath = "/root/cmatrix-1.2a.tar.gz" # 本地檔案路徑
rpackpath = "/tmp/test"  #遠端檔案路徑

@task
def put_task():
        run("mkdir -p /tmp/test")
        with settings(warn_only=True):
                result = put(lpackpath, rpackpath)
                if result.failed and not confirm("put file failed.Continue[Y/N]?"):
                        abort("Aborting file put file!")
                                                        
@task
def run_task():   # 執行遠端命令
        with cd("/tmp/test"):
                run("tar -zxvf cmatrix-1.2a.tar.gz")
                run("ls -l")
                                                                                                    
@task
def go():  # 執行函式
        put_task()
        run_task()
        
        
執行結果:
# fab -f fab_simple3.py go
[192.168.165.45] Executing task 'go'
[192.168.165.45] run: mkdir -p /tmp/test
[192.168.165.45] put: /root/cmatrix-1.2a.tar.gz -> /tmp/test/cmatrix-1.2a.tar.gz
[192.168.165.45] run: tar -zxvf cmatrix-1.2a.tar.gz
[192.168.165.45] out: cmatrix-1.2a/
...
[192.168.165.45] out: 

[192.168.165.45] run: ls -l
[192.168.165.45] out: total 80
[192.168.165.45] out: drwxrwxrwx 2  500  500  4096 Apr  1  2002 cmatrix-1.2a
[192.168.165.45] out: -rw-r--r-- 1 root root 74376 Aug 23 11:34 cmatrix-1.2a.tar.gz
[192.168.165.45] out: 

[192.168.165.38] Executing task 'go'
[192.168.165.38] run: mkdir -p /tmp/test
[192.168.165.38] put: /root/cmatrix-1.2a.tar.gz -> /tmp/test/cmatrix-1.2a.tar.gz
[192.168.165.38] run: tar -zxvf cmatrix-1.2a.tar.gz
[192.168.165.38] out: cmatrix-1.2a/
...
[192.168.165.38] out: 

[192.168.165.38] run: ls -l
[192.168.165.38] out: total 80
[192.168.165.38] out: drwxrwxrwx 2  500  500  4096 Apr  1  2002 cmatrix-1.2a
[192.168.165.38] out: -rw-r--r-- 1 root root 74376 Aug 23 11:30 cmatrix-1.2a.tar.gz
[192.168.165.38] out: 

Done.
Disconnecting from 192.168.165.38... done.
Disconnecting from 192.168.165.45... done.
Disconnecting from 192.168.165.42... done.

參考文件:《python自動化運維 技術與最佳實戰》

相關文章