5

pexpect を使用して SSH 経由でファイルが存在するかどうかをテストしようとしています。ほとんどのコードは機能していますが、ファイルが存在するかどうかを確認できるように、値を取得する必要があります。私が行ったコードは以下のとおりです。

def VersionID():

        ssh_newkey = 'Are you sure you want to continue connecting'
        # my ssh command line
        p=pexpect.spawn('ssh service@10.10.0.0')

        i=p.expect([ssh_newkey,'password:',pexpect.EOF])
        if i==0:
            p.sendline('yes')
            i=p.expect([ssh_newkey,'password:',pexpect.EOF])
        if i==1:
            p.sendline("word")
            i=p.expect('service@main-:')
            p.sendline("cd /opt/ad/bin")
            i=p.expect('service@main-:')
            p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exists"')
            i=p.expect('File Exists')
            i=p.expect('service@main-:')
            assert True
        elif i==2:
            print "I either got key or connection timeout"
            assert False

        results = p.before # print out the result

VersionID()

助けてくれてありがとう。

4

6 に答える 6

9

コマンドの戻りコードが SSH 経由で返されるという事実を利用してみませんか?

$ ssh victory 'test -f .bash_history'
$ echo $?
0
$ ssh victory 'test -f .csh_history'
$ echo $?
1
$ ssh hostdoesntexist 'test -f .csh_history'
ssh: Could not resolve hostname hostdoesntexist: Name or service not known
$ echo $?
255

このようにして、出力をキャプチャする必要なく、リターン コードを確認するだけで済みます。

于 2010-02-03T14:59:29.567 に答える
4

サーバーが sftp セッションを受け入れる場合、私は pexpect を気にせず、代わりに Python 用のparamiko SSH2 モジュールを使用します。

import paramiko
transport=paramiko.Transport("10.10.0.0")
transport.connect(username="service",password="word")
sftp=paramiko.SFTPClient.from_transport(transport)
filestat=sftp.stat("/opt/ad/bin/email_tidyup.sh")

このコードは、サーバーへのSFTPClient接続を開きます。この接続で stat() を使用して、ファイルとディレクトリの存在を確認できます。

ファイルが存在しない場合、sftp.stat は IOError ('No such file') を発生させます。

サーバーが sftp をサポートしていない場合、これは機能します。

import paramiko
client=paramiko.SSHClient()
client.load_system_host_keys()
client.connect("10.10.0.0",username="service",password="word")
_,stdout,_=client.exec_command("[ -f /opt/ad/bin/email_tidyup.sh ] && echo OK")
assert stdout.read()

SSHClient.exec_command はトリプル (stdin、stdout、stderr) を返します。ここでは、出力の存在を確認するだけです。代わりに、コマンドを変更するか、stderr でエラー メッセージを確認してください。

于 2010-02-03T16:35:12.643 に答える
2

プログラムを実行するたびに出力が変わるという問題がありました。たとえば、 を探していた場合/bin/bash、見つかったという結果が返されることもあれば、見つからなかったという結果が返されることもありました。

次のコードが、ファイルとフォルダーに対して一貫して機能するようになりました。\r\n

# returns 0 if the file is missing and 1 if the file exists
# if ( hostFileExists( host, '/bin/sh/' ) == 1 ): echo "File exists!"
def hostFileExists( host, theFile ):
    host.sendline( '[ ! -e %r ] && echo NO || echo YES' % theFile )
    return host.expect( ["\r\nNO", "\r\nYES"] )

また

# provide the host, the command, and the expectation
# command = '[ ! -e "/bin/sh" ] && echo NO || echo YES'
# expecting = ['NO', 'YES']
# i = hostExpect( host, command, expecting )
# if ( i == 1 ): echo "File exists!"
def hostExpect( host, command, expect ):
    newExpect = []
    for e in expect:
        newExpect.append( "\r\n%s" % e )
    host.sendline( command )
    return host.expect( newExpect )

これがお役に立てば幸いです。

編集:また、Windows(cygwin)にsshしてファイルが存在するかどうかを確認しようとすると、ファイルを引用する必要があることに気付きました。Linux では、これはオプションです。そのため、%sinhost.sendlineは に変更されました%r

于 2013-11-11T22:51:20.557 に答える
0

私は私をする解決策に取り組みました。コードは以下のとおりです。

def VersionID(): 

    ssh_newkey = 'Are you sure you want to continue connecting' 
    # my ssh command line 
    p=pexpect.spawn('ssh service@10.10.0.0') 

    i=p.expect([ssh_newkey,'password:',pexpect.EOF]) 
    if i==0: 
        p.sendline('yes') 
        i=p.expect([ssh_newkey,'password:',pexpect.EOF]) 
    if i==1: 
        p.sendline("word") 
        i=p.expect('service@main-:') 
        p.sendline("cd /opt/ad/bin") 
        i=p.expect('service@main-:') 
        p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exists"') 
        i=p.expect('service@main-:') 
        assert True 
    elif i==2: 
        print "I either got key or connection timeout" 
        assert False 


        results = p.before # print out the result
        print results
        value = results.split('"')[8]
        split_value = value.split('\r\n')[1:-1]
        self.assertEquals(split_value, ['File exists'])

これは、「p」から値を文字列形式で抽出します。次に、文字列を分割して文字列 'File Exists' をリストに取得し、探している応答と比較します。ファイルが存在しない場合、テストは失敗します。

すべての助けをありがとう。

于 2010-02-03T16:00:28.807 に答える
0

私は pexpect の経験はありませんが、彼らの Web ページを見ると、expect メソッドを複数の値で呼び出すことができ、一致するもののインデックスを返すように見えます (これは純粋にこの例を見ただけに基づいています)。 .

child.expect('password:')
child.sendline (my_secret_password)
# We expect any of these three patterns...
i = child.expect (['Permission denied', 'Terminal type', '[#\$] '])
if i==0:
    print 'Permission denied on host. Can't login'
    child.kill(0)
elif i==2:
    print 'Login OK... need to send terminal type.'
    child.sendline('vt100')
    child.expect ('[#\$] ')
elif i==3:
    print 'Login OK.'
    print 'Shell command prompt', child.after

実際、あなたはすでにその機能をトップで使用しています。

ファイルが存在するかどうかをキャッチしたいですか?...

これを試して...

        p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exists"')
        file_exists = {0: True, 1: False}[p.expect(('File Exists', 'File does not exists'))]
于 2010-02-03T14:16:39.463 に答える
0

ユーザーが ssh で何かを入力すると、シェルは文字をエコー バックします。それが今も起きています。

だから、やって:

p.sendline('test -f email_tidyup.sh && echo "File exists" || echo "File does not exist"')

次の入力になります。

service@main-: test -f email_tidy.sh && echo "File exists" || echo "File does not exists"
File does not exist

やっている:

i = p.expect(['File exists', 'File does not exist'])

「ファイルが存在します」が返された最初の行に存在するため、常に i==0 になります。

元の送信行に期待される文がない場合の代替案:

p.sendline('test -f email_tidyup.sh; echo result: $?')
i = p.expect('result: 0', 'result: 1')

または、元のように:

p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exist"')
i = p.expect(['\nFile exists', '\nFile does not exist'])
于 2010-02-03T14:25:30.160 に答える