0

Python/Pexpect を使用して、複数のルーターへの SSH セッションを生成しています。コードは 1 つのルーターで機能しますが、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...
4

4 に答える 4

1

私は以前に pexpect でこれに遭遇しました(そして、私がそれをどのように回避したかを思い出そうとしています)。

リターンを送信してからループ内でプロンプトを待つことにより、端末セッションと再同期できます。期待がタイムアウトすると、同期されていることがわかります。

根本的な原因は、おそらく次のいずれかです。

  • 一致を期待せずに send を呼び出す (出力を気にしないため)

  • 出力を生成するコマンドを実行しますが、その出力の途中でパターンを期待し、出力の最後にある次のプロンプトを期待しません。これに対処する 1 つの方法は、期待パターンを「(.+)PROMPT」に変更することです。これは、次のプロンプトまで期待し、送信されたコマンドのすべての出力をキャプチャします (次のステップで解析できます)。

于 2012-09-20T13:43:54.097 に答える
0

これがあなたの問題の根源であるかどうかはわかりませんが、試してみる価値があるかもしれません。

私が遭遇したことは、シェルで開始またはシェルに到達するセッションを生成するときに、TERM タイプの癖 (vt220、color-xterm など) に対処する必要があるということです。カーソルの移動や色の変更に使用される文字が表示されます。この問題は、ほぼ間違いなくプロンプトで表示されます。プロンプトを識別するために探している文字列は、色の変更がどのように処理されるかにより 2 回表示されます (プロンプトが送信され、次にバックスペースへのコードが送信され、色が変更され、プロンプトが再度送信されます... しかし、促す)。

これは、これを処理するものであり、醜く、ハックであり、あまり 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)
于 2015-05-29T19:43:25.417 に答える