下面的类旨在操作类似cisco的设备界面,以执行命令和更新配置元素。
按照目前的情况,我可以实例化该类,调用ssh_to_aos_expsh函数并返回有效的输出(例如,当命令为“show running- config”时,获取配置)。但是,当我调用ssh_to_aos_config函数(它调用ssh_to_aos_expsh函数)时,我得到了一个pexpect超时错误。
我已经将_ssh_connect返回给ssh_to_aos_expsh的pexpect对象( _ssh_connect、ssh_to_aos_expsh和ssh_to_aos_config中的“孩子”)与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发布于 2009-11-16 13:45:47
结果发现有两个问题,一旦我知道问题是什么,这两个问题都很容易解决。首先,__init__方法不包含self.aos_config_prompt -当我注释掉我的异常处理代码时,pexpect异常非常清楚地声明了这一点。其次,给定一个类似于‘accelerator( self.aos_config_prompt )#’的配置,pexpect会将其编译成re模块匹配代码,然后它才会匹配包含括号内容的提示符。只需对字符串中的圆括号进行转义,匹配就会按预期进行。
发布于 2009-11-13 16:14:38
我猜想,超时的发生是因为ssh_to_aos_config()没有得到它期望的所有输入:对ssh_to_aos_expsh()的调用可能会正常工作,而对expect的后续调用则不会。
因此,一个问题是:超时发生在哪里?您可以通过引发异常而不是返回self._timeout_error(子级)来跟踪这一点。您找到的位置将指向pexpect永远不会获得的输入(因此出现超时),您可以在那里更新代码。
发布于 2009-11-13 16:26:03
如果你得到一个超时,那是因为你没有得到任何你想要的字符串。可能是您收到的是错误消息,或者您期望的提示符是错误的。
启用日志记录来查看整个交互-在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这永远不会编译。我认为这是一个剪切粘贴错误,因为你说你一直在运行代码。
https://stackoverflow.com/questions/1727591
复制相似问题