原文来自:https://www.ibm.com/developerworks/cn/linux/l-cn-pexpect1/index.html
侵删。具体内容可以参见原文,本文仅作为笔记。
Pexpect 是一个用来启动子程序并对其进行自动控制的 Python 模块。 Pexpect 可以用来和像 ssh、ftp、passwd、telnet 等命令行程序进行自动交互。本文章介绍 Pexpect 的主要用法和在实际应用中的注意点。 Python 语言的爱好者,系统管理人员,部署及测试人员都能使用 Pexpect 在自己的工作中实现与命令行交互的自动化。
1、pexpect模块仅在类unix环境中可用,windows暂不可用,或使用Cygwin替代方案。
2、run()函数可以用来执行命令,其作用与python os.system()类似,它是通过Pexpect类实现的,如果路径没有完全给出,则run会使用which命令尝试搜索该命令的路径。
run(command,timeout=-1,withexitstatus=False,events=None, extra_args=None,logfile=None, cwd=None, env=None)
3、spawn()类,用以实现子程序的启动。它有丰富的方法与子程序交互从而实现用户对子程序的控制。
它可以记录日志,将日志指向标准输出,记录输出日志等。
4、使用expect控制子程序。为了控制子程序,等待子程序产生特定输出,做出特定的响应,可以使用expect方法。expect 不断从读入缓冲区中匹配目标正则表达式,当匹配结束时 pexpect 的 before 成员中保存了缓冲区中匹配成功处之前的内容, pexpect 的 after 成员保存的是缓冲区中与目标正则表达式相匹配的内容。
5、send()/sendline()/sendcontrol()这些方法用来向子程序发送命令,模拟输入命令的行为。
6、interact()使用Pexpect让出控制权,用户可以继续当前的会话控制子程序。用户可以输入特定的退出字符跳出,其默认值为“^]”。
实例应用
清单 18. ftp 交互的实例: # This connects to the openbsd ftp site and # downloads the README file. import pexpect child = pexpect.spawn ('ftp ftp.openbsd.org') child.expect ('Name .*: ') child.sendline ('anonymous') child.expect ('Password:') child.sendline ('noah@example.com') child.expect ('ftp> ') child.sendline ('cd pub/OpenBSD') child.expect('ftp> ') child.sendline ('get README') child.expect('ftp> ') child.sendline ('bye')
import re,sys,os from pexpect import * def telnet_login(server,user, passwd,shell_prompt= “#|->”): """ @summary: This logs the user into the given server. It uses the 'shell_prompt' to try to find the prompt right after login. When it finds the prompt it immediately tries to reset the prompt to '#UNIQUEPROMPT#' more easily matched. @return: If Login successfully ,It will return a pexpect object @raise exception: RuntimeError will be raised when the cmd telnet failed or the user and passwd do not match @attention:1. shell_prompt should not include '$',on some server, after sendline (passwd) the pexpect object will read a '$'. 2.sometimes the server's output before its shell prompt will contain '#' or '->' So the caller should kindly assign the shell prompt """ if not server or not user \ or not passwd or not shell_prompt: raise RuntimeError, "You entered empty parameter for telnet_login " child = pexpect.spawn('telnet %s' % server) child.logfile_read = sys.stdout index = child.expect (['(?i)login:', '(?i)username', '(?i)Unknown host']) if index == 2: raise RuntimeError, 'unknown machine_name' + server child.sendline (user) child.expect ('(?i)password:') child.logfile_read = None # To turn off log child.sendline (passwd) while True: index = child.expect([pexpect.TIMEOUT,shell_prompt]) child.logfile_read = sys.stdout if index == 0: if re.search('an invalid login', child.before): raise RuntimeError, 'You entered an invalid login name or password.' elif index == 1: break child.logfile_read = sys.stdout # To tun on log again child.sendline(“PS1=#UNIQUEPROMPT#”) #This is very crucial to wait for PS1 has been modified successfully #child.expect(“#UNIQUEPROMPT#”) child.expect("%s.+%s" % (“#UNIQUEPROMPT#”, “#UNIQUEPROMPT#”)) return child
清单 20. pxssh 示例 import pxssh import getpass try: s = pxssh.pxssh() hostname = raw_input('hostname: ') username = raw_input('username: ') password = getpass.getpass('password: ') s.login (hostname, username, password) s.sendline ('uptime') # run a command s.prompt() # match the prompt print s.before # print everything before the propt. s.sendline ('ls -l') s.prompt() print s.before s.sendline ('df') s.prompt() print s.before s.logout() except pxssh.ExceptionPxssh, e: print "pxssh failed on login." print str(e)