Tes*_*315 3 python pexpect python-2.7
我是python-pexpect的新手.在Tcl /期望当我达到超时时 - 我会回复消息并退出该函数.我试图使用发布的示例代码尝试类似的响应 http://pexpect.svn.sourceforge.net/viewvc/pexpect/trunk/pexpect/examples/sshls.py?revision=489&view=markup
我基于上面的代码 - 如果我给出一个伪造的密码,我希望这只是暂停,打印"ERROR!",并退出程序.但是当我运行它 - 进入'Traceback输出(见下文)时,有人可以帮助我让程序打印"ERROR"并优雅地退出程序.
test@ubuntu:~/scripts$ ./tmout.py
Hostname: 192.168.26.84
User: root
Password:
Timeout exceeded in read_nonblocking().
<pexpect.spawn object at 0xb77309cc>
version: 2.3 ($Revision: 399 $)
command: /usr/bin/ssh
args: ['/usr/bin/ssh', '-l', 'root', '192.168.26.84', '/bin/ls', '-l']
searcher: searcher_re:
0: EOF
buffer (last 100 chars):
Permission denied, please try again.
root@192.168.26.84's password:
before (last 100 chars):
Permission denied, please try again.
root@192.168.26.84's password:
after: <class 'pexpect.TIMEOUT'>
match: None
match_index: None
exitstatus: None
flag_eof: False
pid: 14997
child_fd: 3
closed: False
timeout: 30
delimiter: <class 'pexpect.EOF'>
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1
Traceback (most recent call last):
File "./tmout.py", line 54, in <module>
traceback.print_exc()
NameError: name 'traceback' is not defined
test@ubuntu:~/scripts$
Run Code Online (Sandbox Code Playgroud)
源代码:
#!/usr/bin/env python
"""This runs 'ls -l' on a remote host using SSH. At the prompts enter hostname,
user, and password.
$Id$
"""
import pexpect
import getpass, os
def ssh_command (user, host, password, command):
"""This runs a command on the remote host. This could also be done with the
pxssh class, but this demonstrates what that class does at a simpler level.
This returns a pexpect.spawn object. This handles the case when you try to
connect to a new host and ssh asks you if you want to accept the public key
fingerprint and continue connecting. """
ssh_newkey = 'Are you sure you want to continue connecting'
child = pexpect.spawn('ssh -l %s %s %s'%(user, host, command))
i = child.expect([pexpect.TIMEOUT, ssh_newkey, 'password: '])
if i == 0: # Timeout
print 'ERROR!'
print 'SSH could not login. Here is what SSH said:'
print child.before, child.after
return None
if i == 1: # SSH does not have the public key. Just accept it.
child.sendline ('yes')
child.expect ('password: ')
i = child.expect([pexpect.TIMEOUT, 'password: '])
if i == 0: # Timeout
print 'ERROR!'
print 'SSH could not login. Here is what SSH said:'
print child.before, child.after
return None
child.sendline(password)
return child
def main ():
host = raw_input('Hostname: ')
user = raw_input('User: ')
password = getpass.getpass('Password: ')
child = ssh_command (user, host, password, '/bin/ls -l')
child.expect(pexpect.EOF)
print child.before
if __name__ == '__main__':
try:
main()
except Exception, e:
print str(e)
traceback.print_exc()
os._exit(1)
Run Code Online (Sandbox Code Playgroud)
关于自动执行ssh登录的注意事项:如果您正在考虑使用(p)期望自动执行ssh登录,请考虑使用ssh密钥.作为奖励,ssh密钥比密码更安全.它们比在文件系统上存储纯文本密码安全得多,许多用户都希望这样做.如果您使用ssh代理,则可以键入一次密码以在本地解锁密钥,然后在多个主机上自动使用该密钥进行多次登录.为方便起见,您可以设置或禁用密码到期的时间限制.
首先,您应该导入回溯,因此如果程序中出现意外错误,则traceback.print_exc()可以正常工作.
import getpass, os, traceback
Run Code Online (Sandbox Code Playgroud)
我还创建了一个die()函数,以便在程序退出时关闭ssh.
def die(child, errstr):
print errstr
print child.before, child.after
child.terminate()
exit(1)
Run Code Online (Sandbox Code Playgroud)
删除这一行,因为在下一行添加正确的命令后可能会错误地将它留在那里:
child.expect ('password: ')
Run Code Online (Sandbox Code Playgroud)
正确的行(处理超时)是:
i = child.expect([pexpect.TIMEOUT, 'password: '])
Run Code Online (Sandbox Code Playgroud)
然后替换这个:
child.expect(pexpect.EOF)
print child.before
Run Code Online (Sandbox Code Playgroud)
有了这个:
i = child.expect([pexpect.TIMEOUT, 'Permission denied', pexpect.EOF])
if i == 0:
die(child, 'ERROR!\nSSH timed out. Here is what SSH said:')
elif i == 1:
die(child, 'ERROR!\nIncorrect password Here is what SSH said:')
elif i == 2:
print child.before
Run Code Online (Sandbox Code Playgroud)
此更改将告诉程序检测到错误的密码,或者如果存在未知输入则优雅地超时,而不是引发异常.请注意,如果您的命令运行时间超过默认超时持续时间,则它将在完成之前中止.你需要设置类似于timeout=60参数的东西expect()才能改变它.
此外,None超时后返回无用.相反,打电话给die()谁exit(1):
die(child, 'error message')
Run Code Online (Sandbox Code Playgroud)
这是最终的代码:
#!/usr/bin/env python
"""This runs 'ls -l' on a remote host using SSH. At the prompts enter hostname,
user, and password.
$Id$
"""
import pexpect
import getpass, os, traceback
def ssh_command (user, host, password, command):
"""This runs a command on the remote host. This could also be done with the
pxssh class, but this demonstrates what that class does at a simpler level.
This returns a pexpect.spawn object. This handles the case when you try to
connect to a new host and ssh asks you if you want to accept the public key
fingerprint and continue connecting. """
ssh_newkey = 'Are you sure you want to continue connecting'
child = pexpect.spawn('ssh -l %s %s %s'%(user, host, command))
i = child.expect([pexpect.TIMEOUT, ssh_newkey, 'password: '])
if i == 0: # Timeout
die(child, 'ERROR!\nSSH could not login. Here is what SSH said:')
if i == 1: # SSH does not have the public key. Just accept it.
child.sendline ('yes')
i = child.expect([pexpect.TIMEOUT, 'password: '])
if i == 0: # Timeout
die(child, 'ERROR!\nSSH could not login. Here is what SSH said:')
child.sendline(password)
return child
def die(child, errstr):
print errstr
print child.before, child.after
child.terminate()
exit(1)
def main ():
host = raw_input('Hostname: ')
user = raw_input('User: ')
password = getpass.getpass('Password: ')
child = ssh_command(user, host, password, '/bin/ls -l')
i = child.expect([pexpect.TIMEOUT, 'Permission denied', pexpect.EOF])
if i == 0:
die(child, 'ERROR!\nSSH timed out. Here is what SSH said:')
elif i == 1:
die(child, 'ERROR!\nIncorrect password Here is what SSH said:')
elif i == 2:
print child.before
if __name__ == '__main__':
try:
main()
except Exception, e:
print str(e)
traceback.print_exc()
os._exit(1)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
22741 次 |
| 最近记录: |