0

以下のクラスは、コマンドの実行と設定要素の更新を目的として、シスコのようなデバイスインターフェイスを操作するように設計されています。

現在のところ、クラスをインスタンス化し、ssh_to_aos_expsh関数を呼び出して有効な出力を取得できます(たとえば、コマンドが「showrunning-config」の場合に構成を取得します)。ただし、ssh_to_aos_config関数(関数を呼び出すssh_to_aos_expsh)を呼び出すと、pexpectタイムアウトエラーが発生します。

によって返されたpexpectオブジェクト(、、およびの'子' _ssh_connectssh_to_aos_expshを、ssh_to_aos_configによって返され_ssh_connectssh_to_aos_expshオブジェクトと比較しましたが、同じメモリ位置にあるように見えるため、続行できない理由がわかりません。 pexpectを使用してオブジェクトを操作します。ssh_to_aos_expshssh_toaos_config

私は最も洗練された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
4

3 に答える 3

1

2つの問題があったことがわかりました。どちらも、問題が何であるかを知っていれば簡単に修正できます。まず、__init__メソッドには何も含まれていませんself.aos_config_prompt。例外処理コードをコメントアウトしたときに、pexpect例外が非常に明確に述べているものです。次に、self.aos_config_prompt'accelerator(config)#'のように見える場合、pexpectはそれをreモジュール一致コードにコンパイルします。これは、括弧の内容を含むプロンプトにのみ一致します。文字列の括弧をエスケープするだけで、一致が希望どおりに機能します。

于 2009-11-16T05:45:46.787 に答える
0

タイムアウトが発生する場合は、期待する文字列が取得されていないことが原因です。代わりにエラーメッセージが表示されているか、予期しているプロンプトが間違っている可能性があります。

ロギングを有効にして、相互作用全体を確認します-pexpect 2.3では、これはファイルオブジェクトをchild.logfile属性に割り当てることによって行われます-その後、何が起こっているかを正確に確認できます。これは変更されたと思うので、以前のバージョンのドキュメントを確認してください。

私はあなたのコードにいくつかのことに気づきました:

1)root_promptは空の文字列です。クライアントから何も返されていない場合でも、これは常にすぐに一致します。これが問題の原因である可能性があります。ssh接続関数は、クライアントが他の入力を待機している間に、プロンプトを確認して正常にログインしたと見なします。

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はこれをコンパイルしません。コードを実行していると言っているので、カットアンドペーストエラーだと思います。

于 2009-11-13T08:26:03.007 に答える
0

ssh_to_aos_config()期待するすべての入力を取得できないためにタイムアウトが発生すると思います。への呼び出しssh_to_aos_expsh()はうまく機能する可能性がありますが、後続のへの呼び出しは機能しexpectません。

したがって、質問は次のようになります。タイムアウトはどこで発生しますか?self._timeout_error(child)を返す代わりに、例外を発生させることでこれを追跡できます。あなたが見つけた場所は、pexpectが決して取得しない入力を指しているので(したがってタイムアウト)、そこでコードを更新することができます。

于 2009-11-13T08:14:37.583 に答える