我正在尝试使用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()
感谢您的帮助。
答案 0 :(得分: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 :(得分: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('没有这样的文件')。
如果服务器不支持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是否有任何错误消息。
答案 2 :(得分: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进入Windows(cygwin)并尝试查看文件是否存在时,必须引用该文件。在Linux上,这是可选的。因此%s
中的host.sendline
已更改为%r
。
答案 3 :(得分: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'))]
答案 4 :(得分:0)
当用户在ssh中键入内容时,shell将回显字符。现在也正在发生这种情况。
所以,做:
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,因为“File exists”出现在收到的第一行中。
原始发送行的替代方案,没有预期的句子:
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'])
答案 5 :(得分: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'放入列表中,并将其与我正在寻找的响应进行比较。如果文件不存在,则测试将失败。
感谢您的帮助。