100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > python pexpect_python pexpect模块的使用

python pexpect_python pexpect模块的使用

时间:2018-10-22 02:13:17

相关推荐

python pexpect_python pexpect模块的使用

Pexpect 是一个用来启动子程序并对其进行自动控制的 Python 模块。 Pexpect 可以用来和像 ssh、ftp、passwd、telnet 等命令行程序进行自动交互。

pexpect模块在windows功能有限,在linux系统中用得比较多。

pexpect有两个类或方法用得比较多,一个是pexpect.run() 和pexpect.spawn()

pexpect.run()类似于os.system(),但pexpect.run()会返回执行结果

pexpect.spawn()这个类的功能比较强大,可以用于以下功能:

1. ftp 的使用(注:spawn、expect 和 sendline 的使用)

2. 记录 log(注:logfile、logfile_send和logfile_read的使用)

3. ssh 的使用

4. pxssh 的使用

5. telnet 的使用(注:interact 的使用)

使用注意事项:

1.不能使用linux命令中的管道符重定向符等

2.spawn里面的参数列表里面不要使用变量名

以下是实例:

1.pexpect连接ftp:

#!/usr/bin/env python

import pexpect

# 即将 ftp 所要登录的远程主机的域名

ipAddress = ''

# 登录用户名

loginName = 'root'

# 用户名密码

loginPassword = 'passw0rd'

# 拼凑 ftp 命令

cmd = 'ftp ' + ipAddress

# 利用 ftp 命令作为 spawn 类构造函数的参数,生成一个 spawn 类的对象

child = pexpect.spawn(cmd)

# 期望具有提示输入用户名的字符出现

index = child.expect(["(?i)name", "(?i)Unknown host", pexpect.EOF, pexpect.TIMEOUT])

# 匹配到了 "(?i)name",表明接下来要输入用户名

if ( index == 0 ):

# 发送登录用户名 + 换行符给子程序.

child.sendline(loginName)

# 期望 "(?i)password" 具有提示输入密码的字符出现.

index = child.expect(["(?i)password", pexpect.EOF, pexpect.TIMEOUT])

# 匹配到了 pexpect.EOF 或 pexpect.TIMEOUT,表示超时或者 EOF,程序打印提示信息并退出.

if (index != 0):

print "ftp login failed"

child.close(force=True)

# 匹配到了密码提示符,发送密码 + 换行符给子程序.

child.sendline(loginPassword)

# 期望登录成功后,提示符 "ftp>" 字符出现.

index = child.expect( ['ftp>', 'Login incorrect', 'Service not available',

pexpect.EOF, pexpect.TIMEOUT])

# 匹配到了 'ftp>',登录成功.

if (index == 0):

print 'Congratulations! ftp login correct!'

# 发送 'bin'+ 换行符给子程序,表示接下来使用二进制模式来传输文件.

child.sendline("bin")

print 'getting a file...'

# 向子程序发送下载文件 rmall 的命令.

child.sendline("get rmall")

# 期望下载成功后,出现 'Transfer complete.*ftp>',其实下载成功后,

# 会出现以下类似于以下的提示信息:

# 200 PORT command successful.

# 150 Opening data connection for rmall (548 bytes).

# 226 Transfer complete.

# 548 bytes received in 0.00019 seconds (2.8e+03 Kbytes/s)

# 所以直接用正则表达式 '.*' 将 'Transfer complete' 和提示符 'ftp>' 之间的字符全省去.

index = child.expect( ['Transfer complete.*ftp>', pexpect.EOF, pexpect.TIMEOUT] )

# 匹配到了 pexpect.EOF 或 pexpect.TIMEOUT,表示超时或者 EOF,程序打印提示信息并退出.

if (index != 0):

print "failed to get the file"

child.close(force=True)

# 匹配到了 'Transfer complete.*ftp>',表明下载文件成功,打印成功信息,并输入 'bye',结束 ftp session.

print 'successfully received the file'

child.sendline("bye")

# 用户名或密码不对,会先出现 'Login incorrect',然后仍会出现 'ftp>',但是 pexpect 是最小匹配,不是贪婪匹配,

# 所以如果用户名或密码不对,会匹配到 'Login incorrect',而不是 'ftp>',然后程序打印提示信息并退出.

elif (index == 1):

print "You entered an invalid login name or password. Program quits!"

child.close(force=True)

# 匹配到了 'Service not available',一般表明 421 Service not available, remote server has

# closed connection,程序打印提示信息并退出.

# 匹配到了 pexpect.EOF 或 pexpect.TIMEOUT,表示超时或者 EOF,程序打印提示信息并退出.

else:

print "ftp login failed! index = " + index

child.close(force=True)

# 匹配到了 "(?i)Unknown host",表示 server 地址不对,程序打印提示信息并退出

elif index == 1 :

print "ftp login failed, due to unknown host"

child.close(force=True)

# 匹配到了 pexpect.EOF 或 pexpect.TIMEOUT,表示超时或者 EOF,程序打印提示信息并退出

else:

print "ftp login failed, due to TIMEOUT or EOF"

child.close(force=True)

2.记录log的日志代码

#!/usr/bin/env python

"""

This run a user specified command and log its result.

./command.py [-a] [-c command] {logfilename}

logfilename : This is the name of the log file. Default is command.log.

-a : Append to log file. Default is to overwrite log file.

-c : spawn command. Default is the command 'ls -l'.

Example:

This will execute the command 'pwd' and append to the log named my_session.log:

./command.py -a -c 'pwd' my_session.log

"""

import os, sys, getopt

import traceback

import pexpect

# 如果程序中间出错,打印提示信息后退出

def exit_with_usage():

print globals()['__doc__']

os._exit(1)

def main():

######################################################################

# Parse the options, arguments, get ready, etc.

######################################################################

try:

optlist, args = getopt.getopt(sys.argv[1:], 'h?ac:', ['help','h','?'])

# 如果指定的参数不是’ -a ’ , ‘ -h ’ , ‘ -c ’ , ‘ -? ’ , ‘ --help ’ ,

#‘ --h ’或’ --? ’时,会抛出 exception,

# 这里 catch 住,然后打印出 exception 的信息,并输出 usage 提示信息.

except Exception, e:

print str(e)

exit_with_usage()

options = dict(optlist)

# 最多只能指定一个 logfile,否则出错.

if len(args) > 1:

exit_with_usage()

# 如果指定的是 '-h','--h','-?','--?' 或 '--help',只输出 usage 提示信息.

if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]:

print "Help:"

exit_with_usage()

# 获取 logfile 的名字.

if len(args) == 1:

script_filename = args[0]

else:

# 如果用户没指定,默认 logfile 的名字是 command.log

script_filename = "command.log"

# 如果用户指定了参数 -a,如果之前该 logfile 存在,那么接下来的内容会附加在原先内容之后,

# 如果之前没有该 logfile,新建一个文件,并且接下来将内容写入到该文件中.

if '-a' in options:

fout = open (script_filename, "ab")

else:

# 如果用户没指定参数 -a,默认按照用户指定 logfile 文件名新建一个文件,然后将接下来将内容写入到该文件中.

fout = open (script_filename, "wb")

# 如果用户指定了 -c 参数,那么运行用户指定的命令.

if '-c' in options:

command = options['-c']

# 如果用户没有指定 -c 参数,那么默认运行命令'ls – l'

else:

command = "ls -l"

# logfile 文件的 title

fout.write ('==========Log Tile: IBM developerWorks China==========\n')

# 为接下来的运行命令生成一个 pexpect 的 spawn 类子程序的对象.

p = pexpect.spawn(command)

# 将之前 open 的 file 对象指定为 spawn 类子程序对象的 log 文件.

p.logfile = fout

# 命令运行完后,expect EOF 出现,这时会将 spawn 类子程序对象的输出写入到 log 文件.

p.expect(pexpect.EOF)

#open 完文件,使用完毕后,需关闭该文件.

fout.close()

return 0

if __name__ == "__main__":

try:

main()

except SystemExit, e:

raise e

except Exception, e:

print "ERROR"

print str(e)

traceback.print_exc()

os._exit(1)

注:

运行:./command.py -a -c who cmd.log

运行结束后,cmd.log 的内容为:

IBM developerWorks China

Root :0 -05-12 22:40

Root pts/1 -05-12 22:40 (:0.0)

Root pts/2 -07-05 18:55 (9.77.180.94)

logfile:

只能通过 spawn 类的构造函数指定。在 spawn 类的构造函数通过参数指定 logfile 时,表示开启或关闭 logging 。所有的子程序的 input 和 output 都会被 copy 到指定的 logfile 中。设置 logfile 为 None 表示停止 logging,默认就是停止 logging 。设置 logfile 为 sys.stdout,会将所有东西 echo 到标准输出。

logfile_read和logfile_send:

logfile_read:只用来记录 python 主程序接收到 child 子程序的输出,有的时候你不想看到写给 child 的所有东西,只希望看到 child 发回来的东西。 logfile_send:只用来记录 python 主程序发送给 child 子程序的输入 logfile、logfile_read 和 logfile_send 何时被写入呢? logfile、logfile_read 和 logfile_send 会在每次写 write 和 send 操作后被 flush 。

调用 send 后,才会往 logfile 和 logfile_send 中写入,sendline/sendcontrol/sendoff/write/writeline 最终都会调用 send,所以 sendline 后 logfile 中一定有内容了,只要此时 logfile 没有被 close 。

调用 read_nonblocking 后,才会往 logfile 和 logfile_read 中写入,expect_loop 会调用 read_nonblocking,而 expect_exact 和 expect_list 都会调用 expect_loop,expect 会调用 expect_list,所以 expect 后 logfile 中一定有内容了,只要此时 logfile 没有被 close 。

如果调用的函数最终都没有调用 send 或 read_nonblocking,那么 logfile 虽然被分配指定了一个 file,但其最终结果是:内容为空。见下例:

import pexpect

p = pexpect.spawn( ‘ ls -l ’ )

fout = open ('log.txt', "w")

p.logfile = fout

fout.close()

运行该脚本后,你会发现其实 log.txt 是空的,没有记录 ls -l 命令的内容,原因是没有调用 send 或 read_nonblocking,真正的内容没有被 flush 到 log 中。如果在 fout.close() 之前加上 p.expect(pexpect.EOF),log.txt 才会有 ls -l 命令的内容。

3.ssh的使用

#!/usr/bin/env python

"""

This runs a command on a remote host using SSH. At the prompts enter hostname,

user, password and the command.

"""

import pexpect

import getpass, os

#user: ssh 主机的用户名

#host:ssh 主机的域名

#password:ssh 主机的密码

#command:即将在远端 ssh 主机上运行的命令

def ssh_command (user, host, password, command):

"""

This runs a command on the remote host. This could also be done with the

pxssh class, but this demonstrates what that class does at a simpler level.

This returns a pexpect.spawn object. This handles the case when you try to

connect to a new host and ssh asks you if you want to accept the public key

fingerprint and continue connecting.

"""

ssh_newkey = 'Are you sure you want to continue connecting'

# 为 ssh 命令生成一个 spawn 类的子程序对象.

child = pexpect.spawn('ssh -l %s %s %s'%(user, host, command))

i = child.expect([pexpect.TIMEOUT, ssh_newkey, 'password: '])

# 如果登录超时,打印出错信息,并退出.

if i == 0: # Timeout

print 'ERROR!'

print 'SSH could not login. Here is what SSH said:'

print child.before, child.after

return None

# 如果 ssh 没有 public key,接受它.

if i == 1: # SSH does not have the public key. Just accept it.

child.sendline ('yes')

child.expect ('password: ')

i = child.expect([pexpect.TIMEOUT, 'password: '])

if i == 0: # Timeout

print 'ERROR!'

print 'SSH could not login. Here is what SSH said:'

print child.before, child.after

return None

# 输入密码.

child.sendline(password)

return child

def main ():

# 获得用户指定 ssh 主机域名.

host = raw_input('Hostname: ')

# 获得用户指定 ssh 主机用户名.

user = raw_input('User: ')

# 获得用户指定 ssh 主机密码.

password = getpass.getpass()

# 获得用户指定 ssh 主机上即将运行的命令.

command = raw_input('Enter the command: ')

child = ssh_command (user, host, password, command)

# 匹配 pexpect.EOF

child.expect(pexpect.EOF)

# 输出命令结果.

print child.before

if __name__ == '__main__':

try:

main()

except Exception, e:

print str(e)

traceback.print_exc()

os._exit(1)

4. pxssh的使用

#!/usr/bin/env python

import pxssh

import getpass

try:

# 调用构造函数,创建一个 pxssh 类的对象.

s = pxssh.pxssh()

# 获得用户指定 ssh 主机域名.

hostname = raw_input('hostname: ')

# 获得用户指定 ssh 主机用户名.

username = raw_input('username: ')

# 获得用户指定 ssh 主机密码.

password = getpass.getpass('password: ')

# 利用 pxssh 类的 login 方法进行 ssh 登录,原始 prompt 为'$' , '#'或'>'

s.login (hostname, username, password, original_prompt='[$#>]')

# 发送命令 'uptime'

s.sendline ('uptime')

# 匹配 prompt

s.prompt()

# 将 prompt 前所有内容打印出,即命令 'uptime' 的执行结果.

print s.before

# 发送命令 ' ls -l '

s.sendline ('ls -l')

# 匹配 prompt

s.prompt()

# 将 prompt 前所有内容打印出,即命令 ' ls -l ' 的执行结果.

print s.before

# 退出 ssh session

s.logout()

except pxssh.ExceptionPxssh, e:

print "pxssh failed on login."

print str(e)

5.telnet 的使用

#!/usr/bin/env python

import pexpect

# 即将 telnet 所要登录的远程主机的域名

ipAddress = ''

# 登录用户名

loginName = 'root'

# 用户名密码

loginPassword = 'passw0rd'

# 提示符,可能是’ $ ’ , ‘ # ’或’ > ’

loginprompt = '[$#>]'

# 拼凑 telnet 命令

cmd = 'telnet ' + ipAddress

# 为 telnet 生成 spawn 类子程序

child = pexpect.spawn(cmd)

# 期待'login'字符串出现,从而接下来可以输入用户名

index = child.expect(["login", "(?i)Unknown host", pexpect.EOF, pexpect.TIMEOUT])

if ( index == 0 ):

# 匹配'login'字符串成功,输入用户名.

child.sendline(loginName)

# 期待 "[pP]assword" 出现.

index = child.expect(["[pP]assword", pexpect.EOF, pexpect.TIMEOUT])

# 匹配 "[pP]assword" 字符串成功,输入密码.

child.sendline(loginPassword)

# 期待提示符出现.

child.expect(loginprompt)

if (index == 0):

# 匹配提示符成功,输入执行命令 'ls -l'

child.sendline('ls -l')

# 立马匹配 'ls -l',目的是为了清除刚刚被 echo 回显的命令.

child.expect('ls -l')

# 期待提示符出现.

child.expect(loginprompt)

# 将 'ls -l' 的命令结果输出.

print child.before

print "Script recording started. Type ^] (ASCII 29) to escape from the script

shell."

# 将 telnet 子程序的执行权交给用户.

child.interact()

print 'Left interactve mode.'

else:

# 匹配到了 pexpect.EOF 或 pexpect.TIMEOUT,表示超时或者 EOF,程序打印提示信息并退出.

print "telnet login failed, due to TIMEOUT or EOF"

child.close(force=True)

else:

# 匹配到了 pexpect.EOF 或 pexpect.TIMEOUT,表示超时或者 EOF,程序打印提示信息并退出.

print "telnet login failed, due to TIMEOUT or EOF"

child.close(force=True)

更详细的情况请查看:

/mmdln/p/9006274.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。