2010-02-03 27 views
4

我正在尝试使用pexpect测试SSH是否存在于SSH上。我已经得到了大部分代码的工作,但我需要捕捉值,以便我可以断言文件是否存在。我所做的代码如下:通过ssh验证文件是否存在

def VersionID(): 

     ssh_newkey = 'Are you sure you want to continue connecting' 
     # my ssh command line 
     p=pexpect.spawn('ssh [email protected]') 

     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('[email protected]:') 
      p.sendline("cd /opt/ad/bin") 
      i=p.expect('[email protected]:') 
      p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exists"') 
      i=p.expect('File Exists') 
      i=p.expect('[email protected]:') 
      assert True 
     elif i==2: 
      print "I either got key or connection timeout" 
      assert False 

     results = p.before # print out the result 

VersionID() 

感谢您的任何帮助。

+1

@chrissygormley - 我不假设您会考虑使用ssh-agent存储您的密码?如果你这样做,你可以完全避免pexpect,只是做:ssh user @ host“command” –

+0

我已经发布了我的答案在下面的这个问题。谢谢 – chrissygormley

回答

3

如果服务器接受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返回三(标准输入,标准输出,标准错误)。在这里,我们只是检查任何输出的存在。相反,您可以改变命令或检查stderr是否有错误消息。

+0

@flight - 我得到一个错误:---- paramiko.SSHException:通道关闭.-- - 所有的细节输入正确,你知道为什么吗?谢谢 – chrissygormley

+0

@chrissygormley:“sftp [email protected]”是否适合您(即在shell中)? – flight

+0

@flight - sftp适用于其他机器,但是我登录的摄像机正在被拒绝。我会看看如何解决这个问题并再次尝试上面的代码。谢谢 – chrissygormley

0

我没有任何pexpect的经验,但看着他们的网页,它看起来像你可以用多个值调用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'))] 
0

当你作为用户类型的东西在SSH,外壳将回显字符背部。现在也在发生。

那么,这样做的:

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

将导致输入:

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

这时总会导致我== 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']) 
+0

@Johan我尝试了你提供的解决方案。当文件存在i == 0但是当文件不存在时i == 0。 – chrissygormley

+0

方括号版本**完全**与'测试'版本相同。 –

+0

@丹尼斯你是对的。我已经从答案中删除了该部分。 – Johan

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 

这样,您可以检查返回代码而无需捕获输出。

+1

(是啊,我写了shell脚本...用Python写作留给读者一个练习:)) – MikeyB

0

我工作过的解决方案,将做我。代码如下:

def VersionID(): 

    ssh_newkey = 'Are you sure you want to continue connecting' 
    # my ssh command line 
    p=pexpect.spawn('ssh [email protected]') 

    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('[email protected]:') 
     p.sendline("cd /opt/ad/bin") 
     i=p.expect('[email protected]:') 
     p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exists"') 
     i=p.expect('[email protected]:') 
     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'并将其与我正在寻找的响应进行比较。如果文件不存在,则测试将失败。

感谢您的帮助。

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) 

希望这有助于你。

编辑:也注意到,当ssh'ing到Windows(cygwin),并试图查看文件是否存在,文件必须引用。在Linux上,这是可选的。因此host.sendline中的%s更改为%r

相关问题