[英]Python / Pexpect before output out of sync
我正在使用Python / Pexpect生成到多个路由器的SSH会话。 该代码将适用于一个路由器,但是session.before的输出将与某些路由器不同步,因此它将返回前一个sendline的输出。 发送空白行(sendline())时尤其如此。 任何人有任何想法吗? 任何见解将不胜感激。
以下是我所看到的示例:
ssh_session.sendline('sh version')
while (iresult==2):
iresult = ssh_session.expect(['>','#','--More--'],timeout=SESSION_TIMEOUT)
debug_print("execute_1 " + str(iresult))
debug_print("execute_bef " + ssh_session.before)
debug_print("execute_af " + ssh_session.after)
thisoutput = ssh_session.before
output += thisoutput
if(iresult==2):
debug_print("exec MORE")
ssh_session.send(" ")
else:
debug_print("exec: end loop")
for cmd in config_commands:
debug_print("------------------------------------------------\n")
debug_print ("running command " + cmd.strip() + "\n")
iresult=2
ssh_session.sendline(cmd.strip())
while (iresult==2):
iresult = ssh_session.expect([prompt+">",prompt+"#"," --More-- "],timeout=SESSION_TIMEOUT)
thisoutput = ssh_session.before
debug_print("execute_1 " + str(iresult))
debug_print("execute_af " + ssh_session.after)
debug_print("execute_bef " + thisoutput)
thisoutput = ssh_session.before
output += thisoutput
if(iresult==2):
debug_print("exec MORE")
ssh_session.send(" ")
else:
debug_print("exec: end loop")
I get this:
logged in
exec: sh version
execute_1 1
execute_bef
R9
execute_af #
exec: end loop
------------------------------------------------
running command config t
execute_1 1
execute_af #
execute_bef sh version
Cisco IOS Software, 1841 Software (C1841-IPBASEK9-M), Version 15.1(4)M4, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport...
我以前曾以pexpect遇到过这个问题(并且我想记住自己是如何工作的)。
您可以通过发送返回值,然后在循环中期待提示来与终端会话重新同步。 当期望超时时,您就知道自己已同步。
根本原因可能是您是:
调用send时没有预期的匹配(因为您不关心输出)
运行一个产生输出的命令,但期望在该输出的中间有一个模式,然后不要到输出末尾的下一个提示符。 解决此问题的一种方法是将您的期望模式更改为“(。+)PROMPT”-这将一直等到下一个提示符并捕获已发送命令的所有输出(您可以在下一步中进行分析)。
我遇到了类似的问题。 我尝试等待命令在屏幕上打印并发送回车。
我要执行命令“ cmd”,然后执行以下操作:
session.send(cmd)
index = session.expect([cmd, pexpect.TIMEOUT], 1)
session.send('\n')
index = session.expect([whatever you expect])
为我工作。
我不确定这是否是您问题的根源,但可能值得尝试。
我遇到的一个问题是,当您生成一个以shell开头或登陆您的会话时,您必须处理TERM类型(vt220,color-xterm等)的怪癖。 您将看到用于移动光标或更改颜色的字符。 几乎可以保证在提示中出现问题。 由于要处理颜色更改,您正在寻找的用于标识提示的字符串出现了两次(发送提示,然后编码到退格键,更改颜色,然后再次发送提示...但是希望看到两个实例提示)。
以下是处理此问题的方法,保证它们丑陋,hacky,不是非常Pythonic且功能强大:
import pexpect
# wait_for_prompt: handle terminal prompt craziness
# returns either the pexpect.before contents that occurred before the
# first sighting of the prompt, or returns False if we had a timeout
#
def wait_for_prompt(session, wait_for_this, wait_timeout=30):
status = session.expect([wait_for_this, pexpect.TIMEOUT, pexpect.EOF], timeout=wait_timeout)
if status != 0:
print 'ERROR : timeout waiting for "' + wait_for_this + '"'
return False
before = session.before # this is what we will want to return
# now look for and handle any additional sightings of the prompt
while True:
try:
session.expect(wait_for_this, timeout=0.1)
except:
# we expect a timeout here. All is normal. Move along, Citizen.
break # get out of the while loop
return before
s = pexpect.spawn('ssh me@myserver.local')
s.expect('password') # yes, we assume that the SSH key is already there
# and that we will successfully connect. I'm bad.
s.sendline('mypasswordisverysecure') # Also assuming the right password
prompt = 'me$'
wait_for_prompt(s, prompt)
s.sendline('df -h') # how full are my disks?
results = wait_for_prompt(s, prompt)
if results:
print results
sys.exit(0)
else:
print 'Misery. You lose.'
sys.exit(1)
我知道这是一个旧线程,但是在网上并没有太多了解,我只是为此做出了自己的快速变通方法。 我还使用pexpect来遍历网络设备列表并记录统计信息等等,并且我的pexpect.spawn.before有时也会不同步。 由于某种原因,这种情况经常发生在更快,更现代的设备上。
我的解决方案是在每个命令之间编写一个空回车,并检查.before变量的len()。 如果它太小,则意味着它仅捕获了提示,这意味着它必须在实际ssh会话之后至少有一个命令。 如果是这样,该程序将发送另一个空行,以将所需的实际数据移动到.before变量中:
def new_line(this, iteration):
if iteration > 4:
return data
else:
iteration+=1
this.expect(":")
this.sendline(" \r")
data = this.before
if len(data) < 50:
# The numer 50 was chosen because it should be longer than just the hostname and prompt of the device, but shorter than any actual output
data = new_line(this, iteration)
return data
def login(hostname):
this = pexpect.spawn("ssh %s" % hostname)
stop = this.expect([pexpect.TIMEOUT,pexpect.EOF,":"], timeout=20)
if stop == 2:
try:
this.sendline("\r")
this.expect(":")
this.sendline("show version\r")
version = new_line(this,0)
this.expect(":")
this.sendline("quit\r")
return version
except:
print 'failed to execute commands'
this.kill(0)
else:
print 'failed to login'
this.kill(0)
我通过递归命令完成此操作,该命令将自行调用,直到.before变量最终捕获命令的输出为止,或者直到它自行调用5次为止,在这种情况下,它只是放弃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.