您的位置:首页 > 其它

pexpect 初坑

2016-03-09 22:46 176 查看
通过一个很坑的任务,最近认识了一个新坑: pexpect 。其实基本的用法并不难,不过,我还是跟以前一样,把几个基本函数的坑蹚了个遍。有感而发,记录一下。
首先简单的介绍一下这个坑,哦不对,这个库。这是一个 linux 下做SSH 远程登录和操作的库。我们平时用 windows 连接linux 的话,一定很熟悉 SecureCRT ,putty 这样的工具,这些工具就是通过 SSH 做远程连接的。pexpect正是这样一个库,如果有兴趣的话,使用这个库就可以做出一个 SSH 连接的工具。
然后介绍一下这个库的基本使用方法:
通过 pip install pexpect 可以方便的安装上这个库,然后,在代码中引入包:

from pexpect import pxssh


使用时先建立一个对象

ssh = pxssh.pxssh()


然后登录到远程的 linux 机器上

ssh.login(server, username, password, port, login_timeout)


接下来是程咬金的三板斧

# 向 linux发送命令,返回一个长度(源码中写了这个长度是什么,不过我没太看懂)
ssh.sendline(cmd)
# 接收返回的命令(接收成功即为 True ,不管命令执行结果是什么)
ssh.prompt()
# 接收到的返回值的内容
ret = ssh.before


这个时候只要

print ret


就可以看到结果了。
最后别忘了

ssh.logout()


退出。

常用的方法就这些,有一些比较高级的用法我还没有玩,我的任务对这个库的使用就仅限于此了。辣么问题来了,博主484sa,这都玩不明白?
呵呵。
下面讲讲坑吧。
坑一,只能在 linux或unix下使用。
这是由于这个模块使用了一个叫pty的东西,这个是POSIX标准,windows里面并没有。第一次用的时候,在windows下面调了一阵子,又百度了一阵子才知道。浪费时间。
坑二,一个对象只能登录一次。
不管有没有退出,再次 login 都会出错。再次登录只会报错:AssertionError: The pid member must be None. 从这个错误字面上看起来是可以解决的,然而不知道何解。要想再登录只能新建一个对象。
坑三,prompt() 如果不设置timeout,就基本只会返回 True,或者傻等着。
它不抛异常啊!不timeout不返回False啊!就一个黑洞洞的窗口里面一个光标孤独寂寞的闪啊!
坑四,sudo 的处理相当不善良。
我们知道一个“正常”的shell里面sudo一条命令,之后是要输入密码的。然而pexpect不会自动识别。sendline(sudo xxx)之后,再prompt()就会出现上一条的情况:没有然后了!处理方法就是:给prompt设置一个timeout,等待返回,如果返回False,就再sendline一下,把密码发送过去。接下来就正常了,ssh.prompt()接收结果,print ssh.before看结果。注意,这里第一行显示的不是刚才那条命令,而是 [sudo] password for xxx:
坑五, ssh.before 返回的第一行是原命令。并且是有缓冲区的。
很诡异的每 70 字节后面加上一个 \r。 print 的时候就会看到命令循环从这一行开头开始覆盖。解决方法就是把\r给replace掉。
坑六, 不容易看出命令是否执行成功,只能通过 ssh.before 的内容来判断。
某次执行命令,无论如何都看不出来结果,调试了N长时间,最后发现在登录时候就已经超时,未登录成功,导致后面的发送命令都没有进行。

唉。本来我写的那个脚本里面业务逻辑就复杂,然后这个库也跟着捣乱,导致写起来各种吐血。现在终于把脚本写完了,把这个库的初步使用方法记录一下。详细使用方法有两篇IBM写的,传送门:
https://www.ibm.com/developerworks/cn/linux/l-cn-pexpect1/
https://www.ibm.com/developerworks/cn/linux/l-cn-pexpect2/
码了以后看(又码又码,博主你啥时候看过?)。有需要的自行翻看。或者去看一看这个库的源码。有些地方写了例子如何使用,不是很难,就是有一些涉及到操作系统底层和SSH相关协议的地方,没接触过表示看不懂。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: