Saturday, May 23, 2009

Python| How to access ssh with pexpect? ssh automation

Python: How to access ssh with pexpect? » Linux by Examples

I have research on how to access ssh using scripting language for quite sometimes. For python, there are three libs is in my list:

  • Twisted - an event-driven networking engine written in Python.
  • Paramiko - implements the SSH2 protocol for secure connections to remote machines.
  • Pexpect - spawn a child application and control it as if a human were typing commands.
  • Three libraries have used different approach to gain access to ssh, and finally I choose pexpect for the simplicity. This post will briefly shows you how easy you can access ssh with pexpect lib.

    Pexpect allows you to wait for certain STDOUT, and reacts back by sending your lines back to the 'shell'. There are three situation while accessing ssh:

    1. Ssh to the remote site for the first time will trigger this:

    The authenticity of host 'myremote (192.168.1.133)' can't be established. RSA key fingerprint is 4d:78:9b:c2:6d:d7:dc:c2:96:f2:95:69:6a:08:f5:1b. Are you sure you want to continue connecting (yes/no)?


    So you are suppose to answer yes.

    2. Next it will ask you for password:

    mysurface@myremote's password:

    3. No password is needed at all, because you have already have the key.

    To cater all thiese three scenarios, lets look at the python script

     #!/usr/bin/env python import pexpect  ssh_newkey = 'Are you sure you want to continue connecting' # my ssh command line p=pexpect.spawn('ssh mysurface@192.168.1.105 uname -a')  i=p.expect([ssh_newkey,'password:',pexpect.EOF]) if i==0:     print "I say yes"     p.sendline('yes')     i=p.expect([ssh_newkey,'password:',pexpect.EOF]) if i==1:     print "I give password",     p.sendline("mypassword")     p.expect(pexpect.EOF) elif i==2:     print "I either got key or connection timeout"     pass print p.before # print out the result 

    If connection failed, EOF will be captured and you message as below will be print.

    ssh: connect to host 192.168.1.105 port 22: No route to host

    Else, results of uname -a will be print out by print p.before.

    What If I wanna stay connect to ssh, and able to send my input myself?
    You need to enable interactive mode,

    #!/usr/bin/env python import pexpect import struct, fcntl, os, sys, signal  def sigwinch_passthrough (sig, data):     # Check for buggy platforms (see pexpect.setwinsize()).     if 'TIOCGWINSZ' in dir(termios):         TIOCGWINSZ = termios.TIOCGWINSZ     else:         TIOCGWINSZ = 1074295912 # assume     s = struct.pack ("HHHH", 0, 0, 0, 0)     a = struct.unpack ('HHHH', fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ , s))     global global_pexpect_instance     global_pexpect_instance.setwinsize(a[0],a[1])  ssh_newkey = 'Are you sure you want to continue connecting' p=pexpect.spawn('ssh mysurface@192.168.1.105') i=p.expect([ssh_newkey,'password:',pexpect.EOF,pexpect.TIMEOUT],1) if i==0:     print "I say yes"     p.sendline('yes')     i=p.expect([ssh_newkey,'password:',pexpect.EOF]) if i==1:     print "I give password",     p.sendline("mypassword") elif i==2:     print "I either got key or connection timeout"     pass elif i==3: #timeout     pass p.sendline("\r") global global_pexpect_instance global_pexpect_instance = p signal.signal(signal.SIGWINCH, sigwinch_passthrough)  try:     p.interact()     sys.exit(0) except:     sys.exit(1) 

    It seems complicated, yes it is. Pexpect bundle with a lots of examples that illustrate on how to make use of it. The method sigwinch_passthrough is rip out from one of the examples - script.py.

    Download pexpect and start to experience it :D

    Pexpect does not have native support for windows yet, but it works fine on cygwin under windows.

    No comments: