2012-06-06 74 views
0

我正在使用Python/Pexpect爲多個路由器產生一個SSH會話。該代碼適用於一臺路由器,但session.before的輸出將與某些路由器不同步,以便它將返回先前發送線路的輸出。發送空行(sendline())時,情況尤爲如此。任何人有任何想法?任何洞察力將非常感激。輸出不同步之前的Python/Pexpect

下面是我所看到的樣品:

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... 

回答

1

我已經與之前Pexpect的碰上這種情況(我想記得我工作圍繞它)。

您可以通過發送返回然後期待循環中的提示重新與終端會話同步。當期望時間到,那麼你知道你是同步的。

的根本原因可能是,您是:

  • 調用發送不匹配預期(因爲你不關心輸出)

  • 運行產生的輸出命令,但期望在該輸出中間的模式,然後不在輸出結束時的下一個提示。解決這個問題的一種方法是將你期望的模式改變爲「(。+)PROMPT」 - 這將會等到下一個提示並捕獲所發送命令的所有輸出(你可以在下一步中解析)。

+0

感謝您的重新同步的想法,我認爲這是醜陋的,但它適用於我。 – Magentron

0

我遇到過類似的問題。我試着等待命令被打印在屏幕上併發送回車。

我要執行的命令說 'CMD',那麼你就這樣做:

session.send(cmd) 
    index = session.expect([cmd, pexpect.TIMEOUT], 1) 
    session.send('\n') 
    index = session.expect([whatever you expect]) 

爲我工作。

0

我不確定這是問題的根源,但可能值得一試。

我遇到的一件事情是,當你產生一個以shell開頭的會話時,你必須處理TERM類型的怪癖(vt220,color-xterm等)。您將看到用於移動光標或更改顏色的字符。問題幾乎可以保證在提示時出現;由於處理顏色變化的方式(提示被髮送,然後代碼退格,更改顏色,然後再次發送提示...),但您希望看到兩個實例提示)。

這裏的東西處理這個,保證是醜陋,哈克,不是很符合Python和功能:我知道這是一個古老的線程

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 [email protected]') 
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) 
0

,但我沒有找到很多關於這個在線我剛剛通過制定自己的快速和骯髒的解決方法。我還使用pexpect運行網絡設備列表並記錄統計信息等等,而我的pexpect.spawn.before有時也會失去同步。出於某種原因,這種情況經常發生在更快,更現代化的設備上。

我的解決方案是在每個命令之間寫一個空的回車符,並檢查.before變量的len()。如果它太小,則意味着它只捕獲提示,這意味着它必須至少有一個在實際ssh會話後面的命令。如果是這樣的情況下,程序發送另一個空行動,我要到。之前變量的實際數據:

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) 

我做到這一點通過遞歸命令,將調用自身直到。前變量終於捕獲命令的輸出,或直到它自己調用5次,在這種情況下,它只是放棄。