[英]Problem with pexpect and 'chained' function calls
下面的类旨在操纵类cisco的设备接口,以执行命令和更新配置元素。
按照目前的情况,我可以实例化该类,调用ssh_to_aos_expsh
函数并返回有效输出(例如,当命令为“ show running-config”时获取配置)。 但是,当我调用ssh_to_aos_config
函数(该函数调用ssh_to_aos_expsh
函数)时,出现了预期超时错误。
我将_ssh_connect返回_ssh_connect
的ssh_to_aos_expsh
返回的pexpect对象( _ssh_connect
, ssh_to_aos_expsh
和ssh_to_aos_config
的“子”)与ssh_to_aos_config
返回到ssh_to_aos_expsh
的位置的ssh_to_aos_expsh
进行了ssh_toaos_config
,因此看起来不一样为什么我不能继续用pexpect操作对象。
我不是最复杂的python编码器,因此在尝试在函数之间传递pexpect对象时,我可能犯了一些无意的错误,如果是这样,我会感谢有人指出我的错误。
#!/usr/bin/env python
import os
import traceback
import pexpect
class SSHTool():
def __init__(self):
self.aos_user = 'some_user'
self.aos_passwd = 'some_passwd'
self.aos_init_prompt = 'accelerator>'
self.aos_enable_prompt = 'accelerator#'
self.aos_lnxsh_prompt = 'ACC#'
self.linux_passwd = 'linux_passwd'
self.root_prompt = ''
def _timeout_error(self, child):
print 'SSH could not login. Timeout error.'
print child.before, child.after
return None
def _password_error(self, child):
print 'SSH could not login. Password error.'
print child.before, child.after
return None
def _ssh_connect(self, user, address, passwd):
self.root_prompt = "root@%s's password: " % address
ssh_newkey = "Are you sure you want to continue connecting"
child = pexpect.spawn('ssh -l %s %s' % (user, address))
i = child.expect([pexpect.TIMEOUT, \
ssh_newkey, \
'Password: ', \
self.root_prompt])
if i == 0: # Timeout
return self._timeout_error(child)
elif i == 1: # SSH does not have the public key. Just accept it.
child.sendline ('yes')
i = child.expect([pexpect.TIMEOUT, \
'Password: ', \
self.root_prompt])
if i == 0: # Timeout
return self._timeout_error(child)
else:
child.sendline(passwd)
return child
elif i == 2 or i == 3:
child.sendline(passwd)
return child
else:
return self._password_error(child)
def ssh_to_aos_expsh(self, ip_address, command = ''):
child = self._ssh_connect(self.aos_user, \
ip_address, \
self.aos_passwd)
i = child.expect([pexpect.TIMEOUT, \
self.aos_init_prompt])
if i == 0:
return self._timeout_error(child)
child.sendline('enable')
i = child.expect([pexpect.TIMEOUT, \
self.aos_enable_prompt])
if i == 0:
return self._timeout_error(child)
if command:
child.sendline(command)
i = child.expect([pexpect.TIMEOUT, \
self.aos_enable_prompt])
if i == 0:
return self._timeout_error(child)
else:
return child.before
else:
return child
def ssh_to_aos_config(self, ip_address, command):
child = self.ssh_to_aos_expsh(ip_address)
i = child.expect([pexpect.TIMEOUT, \
self.aos_enable_prompt])
if i == 0:
return self._timeout_error(child)
child.sendline('config')
i = child.expect([pexpect.TIMEOUT, \
self.aos_config_prompt])
if i == 0:
return self._timeout_error(child)
child.sendline(command)
i = child.expect([pexpect.TIMEOUT, \
self.aos_config_prompt])
if i == 0:
return self._timeout_error(child)
else:
return child.before
事实证明,存在两个问题,一旦我知道了问题所在,就可以轻松解决。 首先, __init__
方法不包含self.aos_config_prompt
当我注释掉异常处理代码时,pexpect异常非常清楚地说明了这一点。 第二,给定一个self.aos_config_prompt
看起来像“促进剂(配置)#”,Pexpect的编译到这一点re模块匹配的代码,然后只将匹配包含括号的内容的提示。 只需对字符串中的括号进行转义,即可根据需要进行匹配。
我猜想发生超时是因为ssh_to_aos_config()
没有得到它期望的所有输入: ssh_to_aos_expsh()
的调用可能会正常工作,而随后的expect
调用则不会。
因此,问题将是:超时发生在哪里 ? 您可以通过引发异常而不是返回self._timeout_error(child)来跟踪此事件。 您找到的位置将指向预期不会得到的输入(因此会超时),您可以在那里更新代码。
如果超时,那是因为您没有得到期望的任何字符串。 可能是您收到一条错误消息,或者您期望的提示是错误的。
启用日志记录以查看整个交互-在pexpect 2.3中,这是通过将文件对象分配给child.logfile属性来完成的-然后您可以确切地看到正在发生的事情。 检查文档是否有较早的版本,因为我认为这已经改变。
我注意到您的代码中有几件事:
1)root_prompt是一个空字符串。 即使客户端未返回任何内容,这也将始终立即匹配。 这可能是造成问题的原因-ssh connect函数认为它已经看到了提示并成功登录,而客户端仍在等待其他输入。
2)您的代码中存在语法错误-在ssh_connect中,您具有以下顺序:
if i == 0: # Timeout
return self._timeout_error(child)
else:
child.sendline(passwd)
return child
elif i == 2 or i == 3:
child.sendline(passwd)
return child
else:
return self._password_error(child)
Elif与if语句不匹配,因此AFAIK永远不会编译它。 我认为这是剪切和粘贴错误,因为您说您一直在运行代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.