fabric運維

fabric中文文檔:http://fabric-chs.readthedocs.io/zh_CN/chs/python

視頻教程:http://study.163.com/course/courseMain.htm?courseId=1003852044mysql

安裝:    pip3 install fabric3 (注:python3對應要裝fabric3)web

檢查安裝狀況:fab --version正則表達式

       進入python3,sql

       >>> import fabricshell

       >>> dir(fabric)apache

新建目錄:  cd /usr/local/fabricwindows

 

命令行命令:centos

fab -u 用戶名 -p 密碼 -H ‘10.0.0.202’ -- ‘netstat -anptu | grep 22'api

fab -u 用戶名 -p 密碼 -H '10.0.0.202,10.0.0.203,10.0.0.204' -- 'uname-a'

fab -u 用戶名 -p 密碼 -H '10.0.0.203,10.0.0.204' -- 'yum clean all & yum repolist all'

fab -u 用戶名 -p 密碼 -H '10.0.0.203.10.0.0.204' -P(並行) --'reboot'

fab -u 用戶名 -p 密碼 -H '10.0.0.203,10.0.0.204' -P --'yum clean all & yum repolist all'

fab -u 用戶名 -p 密碼 -H '10.0.0.203,10.0.0.204' -- 'system stop firewalld.service' 

fab -u 用戶名 -p 密碼 -H '10.0.0.202,10.0.0.203,10.0.0.204' -P -- 'yum -y install gpm* && service gpm start &&systemctl enable gpm.service'

fab -u用戶名 -p 密碼 -H '10.0.0.204' -- 'yum -y install httpd && systemctl start httpd.service && systemctl enable httpd.service'

瀏覽器輸入10.0.0.204,能夠進入apache界面,爲安裝正常

fab -u用戶名 -p 密碼 -H '10.0.0.204' -- 'netstat -anptu | grep 80'

 

備註:CentOS7服務使用方法

服務使用方法
systemctl start [服務文件名]
systemctl restart [服務文件名]
systemctl stop [服務文件名]
systemctl status [服務文件名]
設置開機啓動
systemctl enable [服務文件名]
systemctl disable [服務文件名]

fabfile文件:

env.hosts = ['10.0.0.203','10.0.0.204'] 定義Ip或主機名列表

env.user = 'root'          定義用戶名

env.port = 22            定義端口

env.password = '密碼'         定義密碼

env.password={'root@10.0.0.203:22':"密碼",

       'root@10.0.0.204:22':「密碼」}  定義用戶名、ip、端口、密碼

env.gateway = '10.0.0.254'     定義網關

env.roledefs = {"webservice":["10.0.0.203","10.0.0.204"],

       "dbservice":["10.0.0.210","10.0.0.211"]  定義角色分租

函數 定義:

from fabric.api import * local #執行本地命令,如local('uname -s') lcd #切換本地目錄,如lcd('/home') cd #切換遠程目錄,如cd('/var/logs') run #執行遠程命令,如run('free -m') sudo #sudo方式執行遠程命令,如sudo('/etc/init.d/httpd start') put #上次本地文件導遠程主機,如put('/home/user.info','/data/user.info') get #從遠程主機下載文件到本地,如:get('/data/user.info','/home/user.info') prompt #得到用戶輸入信息,如:prompt('please input user password:') confirm #得到提示信息確認,如:confirm('Test failed,Continue[Y/N]?') reboot #重啓遠程主機,如:reboot() @task #函數修飾符,標識的函數爲fab可調用的,非標記對fab不可見,純業務邏輯 @runs_once #函數修飾符,標識的函數只會執行一次,不受多臺主機影響 @roles() #運行指定的角色組裏,經過env.roledefs裏的定義 from fabric.colors import * print blue(text) print cyan(text) print green(text) print magenta(text) print red(text) print white(text) print yellow(text)

 

新建文件:  vi fabfile.py  (fab自動調用文檔,其定義的每個函數,就是一個命令)

       fabfile.py中可寫入文檔以下:

         from fabric.api import *

         def host_type():

            run('uname -s')

            run('hostname')

       fab -H localhost host_tpye  (-H localhost指定本機運行)

         env.hosts=[

         'root@10.0.0.2:22',

         'root@10.0.0.3:22']

         env.password = '密碼'

         def host_type():

          run('uname -s')

      fab host_typt

 

新建文件  c.py

from fabric.api import *

env.hosts = ["10.0.0.203","10.0.0.204"]
env.passwords = {
    'root@10.0.0.203:22':'z',
    'root@10.0.0.204:22':'z'}
env.roledefs = {
    'webserver':['10.0.0.204'],
    'dbserver':['10.0.0.203']}


@task
def show():
    run("hostname")
    #run("netstat -anput | grep 22")
    #run("ls /root/")
@task
@roles('webserver')
def install_httpd():
    print('install webserver')

@task
@roles('dbserver')
def install_mysql():
    print('install_mysql')

@task
def run_all():
    execute(show)
    execute(install_httpd)
    execute(install_mysql)
if __name__ == '__main__': execute(run_all)

fab -f c.py -l

fab -f c.py show

fab -f c.py run_all

python3 c.pu  (對應文中if判斷)

 

新建文件  d.py

from fabric.api import *
from fabric.colors import *

env.hosts = ["10.0.0.203","10.0.0.204"]
env.passwords = {
    'root@10.0.0.203:22':'z',
    'root@10.0.0.204:22':'z'}
env.roledefs = {
    'webserver':['10.0.0.204'],
    'dbserver':['10.0.0.203']}
@task
def local_cmd():
    local('ls -la')
    with lcd('/usr/local'):
        local("ls -la")

@task
def runsudo1():
    run('free -m')
    sudo('cat /etc/passwd')

@task
def cd1():
    with cd('/etc'):
        run('ls -la')

@task
def put1():
    put('d.py','/usr/local/')
    run('ls -la /usr/local/')

@task
def get1():
    get('/usr/local/d.py','dd.py')
    local('ls -la')

@task
def prompt1():
    content1 = prompt("請輸入字符:")
    print(content1)

@task    
def color1():
    print(white('hello world!'))
    print(yellow('hello world!'))
    print(red('hello world!'))
    print(blue('hello world!'))
    print(green('hello world!'))
    print(cyan('hello world!'))
    print(magenta('hello world!'))

 confirm

(env1) [root@centos7-3 env1]# python3
>>> from fabric.contrib.console import confirm
>>> content = confirm('continue[Y/N]?')
continue[Y/N]? [Y/n] y
>>> content
True
>>> content = confirm('continue[Y/N]?')
continue[Y/N]? [Y/n] n
>>> content
False

 

文件的打包 、上傳、校驗、下載:

打包:tar -czf xxx.tar.gz.xxx

解包:tar -zxf xxx.tar.gz -C 路徑

上傳:put('本地文件路徑',‘遠程文件路徑’)

下載:get(‘遠程文件路徑’,‘本地文件路徑’)

 新建文件  e.py

 1 from fabric.api import*
 2 from fabric.contrib.console import confirm
 3 from fabric.colors import *
 4 
 5 env.hosts =['10.0.0.204']
 6 env.user = 'root'
 7 
 8 env.passwords = {
 9     'root@10.0.0.203:22':'z',
10     'root@10.0.0.204:22':'z'}
11 
12 @task
13 def upload_file():
14     with settings(warn_only=True):
15         local('tar -czf b.tar.gz b.py')
16         result = put('b.tar.gz','/usr/local/')
17     if result.failed and not confirm('continue[Y/N]?'):
18         abort('put b.tar.gz failed!')
19     with settings(warn_only=True):
20         local_file = local('md5sum b.tar.gz',capture=True).split(" ")[0]
21         remote_file = run('md5sum /usr/local/b.tar.gz').split(" ")[0]
22     if local_file == remote_file:
23         print(green('local == remote'))
24     else:
25         print(red('local != remote'))
26     run('mkdir /usr/local/test')
27     run('tar -zxf /usr/local/b.tar.gz -C /usr/local/test/')
28 
29 @task
30 def download_file():
31     with settings(warn_only=True):
32         get('/usr/local/b.tar.gz','/usr/local/b1.tar.gz')
33         local('mkdir /usr/local/test1')
34         local('tar -zxf /usr/local/b1.tar.gz -C /usr/local/test1')    

 

多主機並行運維:

新建文件夾  f.py

@parallel  #並行

from fabric.api import *
env.user = "root"
host1 = "10.0.0.202"
host2 = "10.0.0.203"
host3 = "10.0.0.204"
env.hosts = [host1,host2,host3]
env.passwords ={
    "root@10.0.0.202:22":"z",
    "root@10.0.0.203:22":"z",
    "root@10.0.0.204:22":"z"}

@task
@parallel
@hosts(host1,host2,host3)
def install_ftp():
    run("yum clean all")
    run("yum repolist all")
    run("yum -y install vsftpd")
    run("systemctl start vsftpd.service")
    run("systemctl enable vsftpd.service")
    run("systemctl status vsftpd.service")

 

 如下文檔轉載自:http://blog.51cto.com/lizhenliang/1880856

第十八章 Python批量管理主機(paramiko、fabric與pexpect)

本章節主要講解運維工程師比較感興趣的知識,那就是運維批量管理,在Python下有paramiko、fabric和pexpect這三個模塊可幫助運維實現自動化部署、批量執行命令、文件傳輸等常規任務,接下來一塊兒看看它們的使用方法吧!

18.1 paramiko

paramiko模塊是基於Python實現的SSH遠程安全鏈接,用於SSH遠程執行命令、文件傳輸等功能。

默認Python沒有,須要手動安裝:pip install paramiko

如安裝失敗,能夠嘗試yum安裝:yum install python-paramiko

18.1.1 SSH密碼認證遠程執行命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/python
# -*- coding: utf-8 -*-
import  paramiko
import  sys
hostname  =  '192.168.1.215'
port  =  22
username  =  'root'
password  =  '123456'
client  =  paramiko.SSHClient()   # 綁定實例
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname, port, username, password, timeout = 5 )
stdin, stdout, stderr  =  client.exec_command( 'df -h' )    # 執行bash命令
result  =  stdout.read()
error  =  stderr.read()
# 判斷stderr輸出是否爲空,爲空則打印執行結果,不爲空打印報錯信息
if  not  error:
    print  result
else :
    print  error
client.close()

18.1.2 私鑰認證遠程執行命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/python
# -*- coding: utf-8 -*-
import  paramiko
import  sys
hostname  =  '192.168.1.215'
port  =  22
username  =  'root'
key_file  =  '/root/.ssh/id_rsa'
cmd  =  " " .join(sys.argv[ 1 :])
def  ssh_conn(command):
     client  =  paramiko.SSHClient()
     key  =  paramiko.RSAKey.from_private_key_file(key_file)
     client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
     client.connect(hostname, port, username, pkey = key)
     stdin, stdout, stderr  =  client.exec_command(command)   # 標準輸入,標準輸出,錯誤輸出
     result  =  stdout.read()
     error  =  stderr.read()
     if  not  error:
         print  result
     else :
         print  error
     client.close()
if  __name__  = =  "__main__" :
     ssh_conn(cmd)

18.1.3 上傳文件到遠程服務器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/python
# -*- coding: utf-8 -*-
import  os, sys
import  paramiko
hostname  =  '192.168.1.215'
port  =  22
username  =  'root'
password  =  '123456'
local_path  =  '/root/test.txt'
remote_path  =  '/opt/test.txt'
if  not  os.path.isfile(local_path):
     print  local_path  +  " file not exist!"
     sys.exit( 1 )
try :
     =  paramiko.Transport((hostname, port))
     s.connect(username  =  username, password = password)
except  Exception as e:
     print  e
     sys.exit( 1 )
sftp  =  paramiko.SFTPClient.from_transport(s)
# 使用put()方法把本地文件上傳到遠程服務器
sftp.put(local_path, remote_path)       
# 簡單測試是否上傳成功
try :
     # 若是遠程主機有這個文件則返回一個對象,不然拋出異常               
     sftp. file (remote_path) 
     print  "上傳成功."
except  IOError:
     print  "上傳失敗!"
finally :
     s.close()

18.1.4 從遠程服務器下載文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/bin/python
# -*- coding: utf-8 -*-
import  os, sys
import  paramiko
hostname  =  '192.168.1.215'
port  =  22
username  =  'root'
password  =  '123456'
local_path  =  '/root/test.txt'
remote_path  =  '/opt/test.txt'
try :
     =  paramiko.Transport((hostname, port))
     s.connect(username = username, password = password)
     sftp  =  paramiko.SFTPClient.from_transport(s)
except  Exception as e:
     print  e
     sys.exit( 1 )
try :
     # 判斷遠程服務器是否有這個文件
     sftp. file (remote_path)
     # 使用get()方法從遠程服務器拉去文件
     sftp.get(remote_path, local_path)       
except  IOError as e:
     print  remote_path  +  "remote file not exist!"
     sys.exit( 1 )
finally :
     s.close()
# 測試是否下載成功
if  os.path.isfile(local_path):
     print  "下載成功."
else :
     print  "下載失敗!"

18.1.5 上傳目錄到遠程服務器

paramiko模塊並無實現直接上傳目錄的類,已經知道了如何上傳文件,再寫一個上傳目錄的代碼就簡單了,利用os庫的os.walk()方法遍歷目錄,再一個個上傳:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/usr/bin/python
# -*- coding: utf-8 -*-
import  os, sys
import  paramiko
hostname  =  '192.168.1.215'
port  =  22
username  =  'root'
password  =  '123456'
local_path  =  '/root/abc'
remote_path  =  '/opt/abc'
# 去除路徑後面正斜槓
if  local_path[ - 1 = =  '/' :
     local_path  =  local_path[ 0 : - 1 ]
if  remote_path[ - 1 = =  '/' :
     remote_path  =  remote_path[ 0 : - 1 ]
file_list  =  []
if  os.path.isdir(local_path):
     for  root, dirs, files  in  os.walk(local_path):
         for  file  in  files:
             # 獲取文件絕對路徑
             file_path  =  os.path.join(root,  file
             file_list.append(file_path)
else :
     print  path  +  "Directory not exist!"
     sys.exit( 1 )
try :
     =  paramiko.Transport((hostname, port))
     s.connect(username = username, password = password)
     sftp  =  paramiko.SFTPClient.from_transport(s)
except  Exception as e:
     print  e
for  local_file  in  file_list:
     # 替換目標目錄
     remote_file  =  local_file.replace(local_path, remote_path)
     remote_dir  =  os.path.dirname(remote_file)
     # 若是遠程服務器沒目標目錄則建立
     try :
         sftp.stat(remote_dir)
     except  IOError:
         sftp.mkdir(remote_dir)
     print  "%s -> %s"  %  (local_file, remote_file)
     sftp.put(local_file, remote_file)
s.close()

sftp是安全文件傳輸協議,提供一種安全的加密方法,sftp是SSH的一部分,SFTPClient類實現了sftp客戶端,經過已創建的SSH通道傳輸文件,與其餘的操做,以下:

sftp.getcwd() 返回當前工做目錄
sftp.chdir(path) 改變工做目錄
sftp.chmod(path, mode) 修改權限
sftp.chown(path, uid, gid) 設置屬主屬組
sftp.close() 關閉sftp
sftp.file(filename, mode='r', bufsize=-1) 讀取文件
sftp.from_transport(s) 建立SFTP客戶端通道
sftp.listdir(path='.') 列出目錄,返回一個列表
sftp.listdir_attr(path='.') 列出目錄,返回一個SFTPAttributes列表
sftp.mkdir(path, mode=511) 建立目錄
sftp.normalize(path) 返回規範化path
sftp.open(filename, mode='r', bufsize=-1) 在遠程服務器打開文件
sftp.put(localpath, remotepath, callback=None) localpath文件上傳到遠程服務器remotepath
sftp.get(remotepath, localpath, callback=None) 從遠程服務器remotepath拉文件到本地localpath
sftp.readlink(path) 返回一個符號連接目標
sftp.remove(path) 刪除文件
sftp.rename(oldpath, newpath) 重命名文件或目錄
sftp.rmdir(path) 刪除目錄
sftp.stat(path) 返回遠程服務器文件信息(返回一個對象的屬性)
sftp.truncate(path, size) 截取文件大小
sftp.symlink(source, dest) 建立一個軟連接(快捷方式)
sftp.unlink(path) 刪除軟連接

 

 

博客地址:http://lizhenliang.blog.51cto.com

QQ羣:323779636(Shell/Python運維開發羣)

 

18.2 fabric

fabric模塊是在paramiko基礎上又作了一層封裝,操做起來更方便。主要用於多臺主機批量執行任務。

默認Python沒有,須要手動安裝:pip install fabric

如安裝失敗,能夠嘗試yum安裝:yum install fabric

Fabric經常使用API:

API類

描述

示例

local 執行本地命令 local('uname -s')
lcd 切換本地目錄 lcd('/opt')
run 執行遠程命令 run('uname -s')
cd 切換遠程目錄 cd('/opt')
sudo sudo方式執行遠程命令 sudo('/etc/init.d/httpd start')
put 上傳本地文件或目錄到遠程主機 put(remote_path, local_path)
get 從遠程主機下載文件或目錄到本地 put(local_path, remote_path)
open_shell 打開一個shell,相似於SSH鏈接到了遠程主機 open_shell("ifconfig eth0")
prompt 得到用戶輸入信息 prompt('Please input user password: ')
confirm 得到提示信息確認 confirm('Continue[Y/N]?')
reboot 重啓遠程主機 reboot()
@task 函數裝飾器,引用說明函數可調用,不然不可見  
@runs_once 函數裝飾器,函數只會執行一次  

當咱們寫好fabric腳本後,須要用fab命令調用執行任務。

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

fab命令有如下經常使用選項:

選項

描述

-l 打印可用的命令(函數)
--set=KEY=VALUE,... 逗號分隔,設置環境變量
--shortlist 簡短打印可用命令
-c PATH 指定本地配置文件
-D 不加載用戶known_hosts文件
-f PATH 指定fabfile文件
-g HOST 逗號分隔要操做的主機
-i PATH 指定私鑰文件
-k 不加載來自~/.ssh下的私鑰文件
-p PASSWORD 使用密碼認證and/or sudo
-P 默認爲並行執行方法
--port=PORT 指定SSH鏈接端口
-R ROLES 根據角色操做,逗號分隔
-s SHELL 指定新shell,默認是'/bin/bash -l -c'
--show=LEVELS 以逗號分隔的輸出
--ssh-config-path=PATH SSH配置文件路徑
-t N 設置鏈接超時時間,單位秒
-T N 設置遠程命令超時時間,單位秒
-u USER 鏈接遠程主機用戶名
-x HOSTS 以逗號分隔排除主機
-z INT 併發進程數

18.2.1 本地執行命令

1
2
3
4
5
6
7
from  fabric.api  import  local
def  command():
     local( 'ls' )
# fab command
[localhost] local: ls
fabfile.py  fabfile.pyc  tab.py  tab.pyc
Done.

使用fab命令調用,默認尋找當前目錄的fabfile.py文件。

18.2.2 遠程執行命令

1
2
3
4
5
6
7
8
9
10
11
12
from  fabric.api  import  run
def  command():
     run( 'ls' )
# fab -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以逗號分隔便可。

18.2.3 給腳本函數傳入位置參數

1
2
3
4
5
6
7
8
9
10
11
from  fabric.api  import  run
def  hello(name = "world" ):
     print ( "Hello %s!"  %  name)
# fab -H localhost hello
[localhost] Executing task  'hello'
Hello world!
Done.
# fab -H localhost hello:name=Python
[localhost] Executing task  'hello'
Hello Python!
Done.

18.2.4 主機列表組

1
2
3
4
5
6
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' )

env做用是定義fabfile全局設定,相似於變量。還有一些經常使用的屬性:

env屬性

描述

示例

env.hosts 定義目標主機 env.hosts = ['192.168.1.120:22']
env.exclude_hosts 排除指定主機 env.exclude_hosts = '[192.168.1.1]'
env.user 定義用戶名 env.user='root'
env.port 定義端口 env.port='22'
env.password 定義密碼 env.password='123'
env.passwords 定義多個密碼,不一樣主機對應不一樣密碼 env.passwords = {'root@192.168.1.120:22': '123'}
env.gateway 定義網關 env.gateway='192.168.1.2'
env.roledefs 定義角色分組 env.roledef = {'web':['192.168.1.11'], 'db':['192.168.1.12']}
env.deploy_release_dir 自定義全局變量,格式:env.+ '變量名' env.var

18.2.5 定義角色分組

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# vi 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)
# fab -f install.py deploy

18.2.6 上傳目錄到遠程主機

1
2
3
4
5
6
7
8
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' )
# fab task

18.2.7 從遠程主機下載目錄

1
2
3
4
5
6
7
8
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' )
# fab task

18.2.8 打印顏色,有助於關鍵地方醒目

1
2
3
4
5
6
from  fabric.colors  import  *
def  show():
    print  green( 'Successful.' )
    print  red( 'Failure!' )
    print  yellow( 'Warning.' )
# fab show

通過上面演示fabric主要相關功能,是否是以爲很適合批量自動部署呢!沒錯,經過編寫簡單的腳本,便可完成複雜的操做。

 

 

博客地址:http://lizhenliang.blog.51cto.com

QQ羣:323779636(Shell/Python運維開發羣)

 

18.3 pexpect

pexpect是一個用來啓動子程序,並使用正則表達式對程序輸出作出特定響應,以此實現與其自動交互的Python模塊。暫不支持Windows下的Python環境執行。

這裏主要講解run()函數和spawn()類,能完成自動交互,下面簡單瞭解下它們使用。

18.3.1 run()

run()函數用來運行bash命令,相似於os模塊中的system()函數。

參數:run(command, timeout=-1, withexitstatus=False, events=None, extra_args=None, logfile=None, cwd=None, env=None)

1
2
3
4
5
1 :執行ls命令
>>>  import  pexpect
>>> pexpect.run( "ls"
2 :得到命令狀態返回值
>>> command_output, exitstatus  =  pexpect.run( "ls" , withexitstatus = 1 )

command_outout是執行結果,exitstatus是退出狀態值。

18.3.2 spawn()

spawn()是pexpect模塊主要的類,實現啓動子程序,使用pty.fork()生成子進程,並調用exec()系列函數執行命令。

參數:spawn(command, args=[], timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None)

spawn()類幾個經常使用函數:

expect(pattern, timeout=-1, searchwindowsize=None) 匹配正則表達式,pattern能夠是正則表達式。
send(s) 給子進程發送一個字符串
sendline(s='') 就像send(),但添加了一個換行符(os.lineseq)
sendcontrol(char) 發送一個控制符,好比ctrl-c、ctrl-d

例子:ftp交互

用ftp命令登陸是這樣的,須要手動輸入用戶名和密碼,才能登陸進去。

1
2
3
4
5
6
7
8
9
10
11
# ftp 192.168.1.10
Connected to  192.168 . 1.10  ( 192.168 . 1.10 ).
220 - FileZilla Server version  0.9 . 46  beta
220 - written by Tim Kosse (tim.kosse@filezilla - project.org)
220  Please visit http: / / sourceforge.net / projects / filezilla /
Name ( 192.168 . 1.10 :root): yunwei
331  Password required  for  yunwei
Password:
230  Logged on
Remote system  type  is  UNIX.
ftp>

下面咱們用pexpect幫咱們完成輸入用戶名和密碼:

1
2
3
4
5
6
7
8
9
10
11
import  pexpect
child  =  pexpect.spawn( 'ftp 192.168.1.10' )
child.expect( 'Name .*: ' )
child.sendline( 'yunwei' )
child.expect( 'Password:' )
child.sendline( 'yunweipass' )
child.expect( 'ftp> ' )
child.sendline( 'ls' )
child.sendline( 'bye' )
child.expect(pexpect.EOF)    # pexpect.EOF程序打印提示信息
print  child.before    # 保存命令執行結果

手動輸入時,是來自鍵盤的標準輸入,而pexpect是先匹配到關鍵字,再向子進程發送字符串。

pexpect.EOF打印提示信息,child.before保存的是命令執行結果。

經過上面的例子想必你已經知道pexpect主要功能了,在交互場景下頗有用,這裏就講解這麼多了,目的是給你們提供一個自動交互實現思路。

小結:

經過對Python下paramiko、fabric和pexpect模塊使用,它們各有本身擅長的一面。

paramiko:方便嵌套系統平臺中,擅長遠程執行命令,文件傳輸。

fabric:方便與shell腳本結合,擅長批量部署,任務管理。

pexpect:擅長自動交互,好比ssh、ftp、telnet。

相關文章
相關標籤/搜索