Python: How to access ssh with pexpect?
November 25th, 2007 mysurface Posted in python | Hits: 89352 | 9 Comments »
I have research on how to access ssh using scripting language for quite sometimes. For python, there are three libs is in my list:
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.
[tags]pexpect, expect, python ssh, cygwin, python tutorial[/tags]







September 30th, 2009 at 2:39 am
Thanks! That was super helpful.
June 30th, 2010 at 8:15 pm
In 2010 there are more options: subprocess, pexpect, paramiko, python-libssh2, twisted.
August 29th, 2010 at 2:31 am
How can I use above code to write a script, which will run a script in a remote machine via ssh (as described above) and get a variable value to use in local.py script?
local_machine remote_machine
[local.py] [remote.py]
Please help.
July 6th, 2011 at 2:00 am
pexpect has another module that makes this much simplier.
pxssh. It handles all of your extra logic like new key
password prompting and the like. Note Centos5 and the like has a version of pexpect that fails doing the below code.
Here is your example using pxssh module:
————————————–
#!/usr/bin/python
import sys
import pxssh
import getpass
user = ‘root’
try:
host = sys.argv[1]
except IndexError:
print ‘Must have host name or ip address’
sys.exit(1)
password = ‘yourpassword’
try:
s = pxssh.pxssh()
s.force_password = True
s.login (host, user, password, login_timeout=20)
s.sendline (‘uptime’) # run a command
s.prompt() # match the prompt
print s.before,s.after
s.interact()
except pxssh.ExceptionPxssh, e:
print “pxssh failed on login.”
print str(e)
except OSError:
print “End session to ” + user + “@” + host
July 6th, 2011 at 2:02 am
Wow. How really bad that the comment section wacks the formating of the provided code such that it won’t run.
July 15th, 2012 at 6:40 pm
Will this solution work with crontab?
Then you need to add ssh -i to find your .ssh/id_rsa file
October 6th, 2012 at 12:01 am
Hi,
If I use the simple code below to try a simplet connection test:
import pxssh
import getpass
try:
client = pxssh.pxssh()
hostname = raw_input(‘hostname: ‘)
username = raw_input(‘username: ‘)
password = getpass.getpass(‘password: ‘)
client.login(hostname, username, password)
client.sendline(‘uptime’)
client.prompt()
print client.before
client.logout()
except pxssh.ExceptionPxssh, e:
print “pxssh failed on login.”
print str(e)
I receive the error:
Traceback (most recent call last):
File “ssh_dump.py”, line 43, in
client.login(my_host,my_usr,my_pswd)
File “/usr/lib/python2.6/site-packages/pxssh.py”, line 243, in login
if not self.synch_original_prompt():
File “/usr/lib/python2.6/site-packages/pxssh.py”, line 134, in synch_original_prompt
self.read_nonblocking(size=10000,timeout=1) # GAS: Clear out the cache before getting the prompt
File “/usr/lib/python2.6/site-packages/pexpect.py”, line 824, in read_nonblocking
raise TIMEOUT (‘Timeout exceeded in read_nonblocking().’)
pexpect.TIMEOUT: Timeout exceeded in read_nonblocking().
Can you help me?
April 6th, 2013 at 2:05 pm
[...] I am working off of this link: http://linux.byexamples.com/archives/346/python-how-to-access-ssh-with-pexpect/ [...]
April 10th, 2013 at 11:38 am
This is a really great read for me, Have to admit you are 1 in the best bloggers I ever saw.Thanks for posting this informative article.