Source From Here
Question
I'm new to python-pexpect. In Tcl/expect when I hit a timeout - I would respond with message and exit the function. I have tried to experiment with similar response using sample code posted as Below:
- test.py
I based on this code above - if I give a bogus password, I would expect this to just timeout, print "ERROR!", and exit program. But when I run it - goes into a 'Traceback output , can someone help me to get the program to print "ERROR" and exit program gracefully.
How-To
First off, you should import traceback, so if there is an unexpected error in the program, traceback.print_exc() will work.
I also created a
die() function so that ssh gets closed when the program quits.
Delete this line, since it was probably left there by mistake after adding the correct command on the next line:
The correct line (
which handles timeouts) is:
then replace this:
with this:
This change will tell the program to detect a bad password, or to timeout gracefully if there is unknown input, instead of raising an exception. Note that if your command runs longer than the default timeout duration, it will be aborted before it finishes. You'll have to set 'timeout' as you call expect() in order to fix that.
Also returning 'None' after a timeout isn't useful. Instead, call die() which will call exit(1):
This is the final code:
Question
I'm new to python-pexpect. In Tcl/expect when I hit a timeout - I would respond with message and exit the function. I have tried to experiment with similar response using sample code posted as Below:
- test.py
- #!/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)
How-To
First off, you should import traceback, so if there is an unexpected error in the program, traceback.print_exc() will work.
- import getpass, os, traceback
- def die(child, errstr):
- print errstr
- print child.before, child.after
- child.terminate()
- exit(1)
- child.expect ('password: ')
- i = child.expect([pexpect.TIMEOUT, 'password: '])
- child.expect(pexpect.EOF)
- print child.before
- 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
Also returning 'None' after a timeout isn't useful. Instead, call die() which will call exit(1):
- die(child, 'error message')
- #!/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)
沒有留言:
張貼留言