pexpect使用

shell里使用expect不怎么好用,语法太丑陋,现来试试python中的pexpect。

对pxssh的尝试

其实对于登录ssh这种交互操作,python有专门的pxssh:

import pxssh

但是help中的实验代码一直报错,网上的解决方案是修改pxssh中的源码, 太麻烦,决定放弃pxssh,学习使用更通用的pexpect,其实pxssh也就是基于pexpect实现的。报错信息粘贴如下:

Traceback (most recent call last):
  File "test_pxssh.py", line 10, in <module>
    s.login (hostname, username, password)
  File "/usr/lib/python2.7/dist-packages/pxssh.py", line 243, in login
    if not self.synch_original_prompt():
  File "/usr/lib/python2.7/dist-packages/pxssh.py", line 134, in synch_original_prompt
    self.read_nonblocking(size=10000,timeout=1) # GAS: Clear out the cache before getting the prompt
  File "/usr/lib/python2.7/dist-packages/pexpect.py", line 824, in read_nonblocking
    raise TIMEOUT ('Timeout exceeded in read_nonblocking().')
pexpect.TIMEOUT: Timeout exceeded in read_nonblocking().

学习使用pexpect

举个scp的例子:

import pexpect
child = pexpect.spawn('scp ip.html xxx.xxx.xxx.xxx:~/')
child.expect(':', timeout=1)
child.sendline('xxxxx')
child.isalive()
child.expect(pexpect.EOF)
child.close()

特别注意,pexpect会不解析如下一些符号:

| > *

如果你想使用它们,你应该开启一个bash终端,像这面这样:

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

又特别注意,child.expect的第一个参数是匹配参数,会被编译成一个正则对象,所以可以是字符串,也可以是已经编译好的正则对象, 而且可以是一个list,用于逐个尝试,还可以是一个特殊代号,如pexpect.EOF, pexpect.TIMEOUT等。它返回值为正则对象的索引值。 所以你应该这么写:

index = child.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()

而不应该这么写,尽管也是work的:

try:
    index = child.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()

当然有种匹配所有字符的懒惰写法:

index = child.except([r'.*', pexpect.EOF, pexpect.TIMEOUT], timeout=1)

child.before是匹配位置之前的字符串,child.after是匹配的字符串,child.buffer是匹配位置之后的字符串。

还可以通过如下方法,来接管交互,人工介入:

child.interact()

其他

使用如下模块来获取输入可以像获取密码一样,不显示用户的输入内容:

import getpass
res = getpass.getpass()
发表于 2014年10月24日 11:35   评论:0   阅读:4060  



回到顶部

首页 | 关于我 | 关于本站 | 站内留言 | rss
python logo   django logo   tornado logo