系统批量运维管理器pexpect详解

时间:2024-01-20 21:05:06

一、pexpect介绍

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

pexpect官网地址:https://pexpect.readthedocs.io/en/stable/

        https://pypi.org/project/pexpect/

二、pexpect的安装

mac os安装

pip3 install pexpect

CentOS 安装

[root@localhost ~]# pip3 install pexpect
Collecting pexpect
  Downloading https://files.pythonhosted.org/packages/89/e6/b5a1de8b0cc4e07ca1b305a4fcc3f9806025c1b651ea302646341222f88b/pexpect-4.6.0-py2.py3-none-any.whl (57kB)
    100% |████████████████████████████████| 61kB 128kB/s
Collecting ptyprocess>=0.5 (from pexpect)
  Downloading https://files.pythonhosted.org/packages/ff/4e/fa4a73ccfefe2b37d7b6898329e7dbcd1ac846ba3a3b26b294a78a3eb997/ptyprocess-0.5.2-py2.py3-none-any.whl
Installing collected packages: ptyprocess, pexpect
Successfully installed pexpect-4.6.0 ptyprocess-0.5.2

三、pexpect的核心组件

spawn类

spawn是pexpect的主要类接口,功能是启动和控制子应用程序,以下是它的构造函数定义:

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 = open('mylog.txt','wb')
child.logfile = fout

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

# In Python 2:
child = pexpect.spawn('some_command')
child.logfile = sys.stdout

# In Python 3, we'll use the ``encoding`` argument to decode data
# from the subprocess and handle it as unicode:
child = pexpect.spawn('some_command', encoding='utf-8')
child.logfile = sys.stdout

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