python系统批量运维管理器pexpect简介

一 点睛

pexpect可以理解成Linux下的expect的Python封装,通过pexpect我们可以实现对ssh、ftp、passwd、telnet等命令行进行自动交互,而无需人工干涉来达到自动化的目的。比如我们可以模拟一个FTP登录时的所有交互,包括输入主机地址、用户名、密码、上传文件等,待出现异常我们还可以进行尝试自动处理。

pexpect的官网地址: http://pexpect.readthedocs.org/en/latest

二 安装

[root@localhost /]# pip install pexpect

三 spawn类

1 点睛

spawn是pexpect的主要类接口,功能是启动和控制子应用程序

2 构造函数

class pexpect.spawn(command, args=[], timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None, ignore_sighup=True)

command:可以是任意已知的系统命令。

child = pexpect.spawn('/usr/bin/ftp') #启动ftp客户端命令
child = pexpect.spawn('/usr/bin/ssh user@example.com') #启动ssh远程连接命令
child = pexpect.spawn('ls -latr /tmp') #运行ls显示/tmp目录内容命令

当子程序需要参数时,还可以使用Python列表来代替参数项

child = pexpect.spawn ('/usr/bin/ftp', []) 
child = pexpect.spawn ('/usr/bin/ssh', ['user@example.com']) 
child = pexpect.spawn ('ls', ['-latr', '/tmp'])

timeout:等待结果的超时时间

maxread:pexpect从终端控制台一次读取的最大字节数

searchwindowsize:匹配缓冲区字符串的位置,默认是从开始位置匹配。

需要注意的是,pexpect不会解析shell命令当中的元字符,包括重定向“>”、管道“|”或通配符“*”,当然,我们可以通过一个技巧来解决这个问题,将存在这三个特殊元字符的命令作为/bin/bash的参数进行调用。

child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > logs.txt"') 
child.expect(pexpect.EOF)

我们可以通过将命令的参数以Python列表的形式进行替换,从而使我们的语法变成更加清晰。

shell_cmd = 'ls -l | grep LOG > logs.txt' 
child = pexpect.spawn('/bin/bash', ['-c', shell_cmd]) 
child.expect(pexpect.EOF)

有时候调试代码时,希望获取pexpect的输入与输出信息,以便了解匹配的情况。pexpect提供了两种途径,一种为写到日志文件,另一种为输出到标准输出。

child = pexpect.spawn('some_command')
fout = file('mylog.txt','w') 
child.logfile = fout

输出到标准输出的方法如下

child = pexpect.spawn('some_command') 
child.logfile = sys.stdout

下面为一个完整的示例,实现远程SSH登录,登录成功后显示/home目录文件清单,并通过日志文件记录所有的输入与输出

import pexpect
import sys
child = pexpect.spawn('ssh root@192.168.0.104')
fout = file('mylog.txt','w')
child.logfile = fout
#child.logfile = sys.stdout
child.expect('(yes/no)?')
#Are you sure you want to continue connecting (yes/no)?
child.sendline("yes")
child.expect('password: ')
child.sendline("123456")
child.expect('#')
child.sendline('ls /home')
child.expect('#')

下面是mylog.txt文件输出结果,可以看到pexpect产生的全部输入与输出信息。

[root@localhost pymaintain]# cat mylog.txt
yes
yes
\S
Kernel \r on an \m
root@192.168.0.104's password: 123456

Last login: Sun Feb 24 13:22:36 2019 from 192.168.0.120
hello cakin24!
[root@slave2 ~]# ls /home
ls /home
123  av  jt  jzmb  lw  sdf  tony  user1  user3  user4

3 expect方法

expect定义了一个子程序输出的匹配规则。

方法定义:expect(pattern,timeout=–1,searchwindowsize=–1)

其中,参数pattern表示字符串、pexpect.EOF(指向缓冲区尾部, 无匹配项)、pexpect.TIMEOUT(匹配等待超时)、正则表达式或者前面四种类型组成的列表(List),当pattern为一个列表时,且不止一个列表元素被匹配,则返回的结果是子程序输出最先出现的那个元素,或者是列表最左边的元素(最小索引ID)

import pexpect
child = pexpect.spawn("echo 'foobar'")
print child.expect(['bar','foo','foobar'])

输出结果表示foo被匹配

[root@localhost pymaintain]# python 5_2_2.py
1

参数timeout指定等待匹配结果的超时时间,单位为秒。当超时被触发时,expect将匹配到pexpect.TIMEOUT

参数searchwindowsize为匹配缓冲区字符串的位置,默认是从开始位置匹配

当pexpect.EOF、pexpect.TIMEOUT作为expect的列表参数时,匹配时将返回所处列表中的索引ID

index = p.expect(['good', 'bad', pexpect.EOF, pexpect.TIMEOUT]) 
if index == 0:
    do_something() 
elif index == 1:
    do_something_else() 
elif index == 2:
    do_some_other_thing()
elif index == 3:
    do_something_completely_different()

以上代码等价于

try:
    index = p.expect(['good', 'bad'])
    if index == 0:
        do_something()
    elif index == 1:
        do_something_else()
 except EOF:
    do_some_other_thing()
 except TIMEOUT:
    do_something_completely_different()

expect方法有两个非常棒的成员:before与after。before成员保存了最近匹配成功之前的内容,after成员保存了最近匹配成功之后的内容。

示例:

import pexpect
import sys
child = pexpect.spawn('ssh root@192.168.0.104')
fout = file('mylog.txt','w')
#child.logfile = fout
child.logfile = sys.stdout
child.expect('(yes/no)?')
#Are you sure you want to continue connecting (yes/no)?
child.sendline("yes")
child.expect('password: ')
child.sendline("123456")
print "+++++++++++++++"
print "before:"+child.before
print "after:"+child.after
print "+++++++++++++++"
child.expect('#')
child.sendline('ls /home')
child.expect('#')

输出结果:

[root@localhost pymaintain]# python 5_2_1.py
yes
yes
\S
Kernel \r on an \m
root@192.168.0.104's password: 123456
+++++++++++++++
before:yes
\S
Kernel \r on an \m
root@192.168.0.104's
after:password:
+++++++++++++++

Last login: Sun Feb 24 13:49:29 2019 from 192.168.0.120
hello cakin24!

4 read相关方法

下面这些输入方法的作用都是向子程序发送响应命令,可以理解成代替了我们的标准输入键盘。

send(self, s)             # 发送命令,不回车
sendline(self, s='')      # 发送命令,回车
sendcontrol(self, char)   # 发送控制字符,如child.sendcontrol('c')等价于”ctrl+c”
sendeof()                  # 发送eof

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值