2

Need assistance with the pexpect module

I have written a simple code which would clone a git repository from a server using ssh. I'm facing couple of problems.

The password is shown in plain text.

I dont know a proper way to exit the program after the download. it throws out the following error...

Traceback (most recent call last):
File "ToDelete3.py", line 65, in <module>
  # # if i == 1:
File "ToDelete3.py", line 36, in getRepository
  i = p.expect([ssh_key,'password:',pexpect.EOF])
File "/usr/lib/python2.7/dist-packages/pexpect.py", line 1492, in interact
  self.__interact_copy(escape_character, input_filter, output_filter)
File "/usr/lib/python2.7/dist-packages/pexpect.py", line 1520, in __interact_copy
  data = self.__interact_read(self.child_fd)
File "/usr/lib/python2.7/dist-packages/pexpect.py", line 1510, in __interact_read
  return os.read(fd, 1000)
OSError: [Errno 5] Input/output error

the code that I have written so far is :

command = 'git clone ssh://username@someserver/something.git'
ssh_key = 'Are you sure you want to continue connecting'

def gracefulExit():
    print 'Password Incorrect !!!'
    os._exit(1)

def getRepository():
    p = pexpect.spawn(command,maxread=10000,timeout = 100)
    p.logfile = sys.stdout  # logs out the command  
    i = p.expect([ssh_key,'password:',pexpect.EOF])
    if i == 0:
         print 'Inside sshkey'
         p.sendline('yes')
         i = p.expect([ssh_key,'password:',pexpect.EOF])
    if i == 1:
        try:
            p.sendline('mypassword') # this mypassword is shown in clear text on the console
            p.interact()
            p.logfile = sys.stdout
            p.expect(pexpect.EOF)
        except Exception,e:
            print str(e)
            gracefulExit()
    if i == 2:
        print 'Inside EOF block'
        if p.isalive():
            print '******************************************************'
            print '         Closing the process of Download !!!          '
            print '******************************************************\n\n'
            p.close()

Any inputs is highly appreciated..

Thanks. -Vijay

pyfunc
  • 65,343
  • 15
  • 148
  • 136
user596922
  • 1,501
  • 3
  • 18
  • 27

2 Answers2

3

There are few errors in the program:

p.interact()

This is used when we want to get back the control after having automatically supplied the password using pexpect module. You don't need to use that since you are automating the whole repository check out.

Also a few things can be improved, after passing the password, set a infinite timeout since it may take a while to copy a git repository.

p.expect(pexpect.EOF, timeout=None)

After that you can read all the execution output with the following command

output_lines =  p.before
output_lines_list = output_lines.split('\r\n')
for line in output_lines: print line

you can also use the above to log the output to a file by directly writing to it

Using p.logifile = sys.stdout is not good since it will record pexpect operation from start including passing of password.

After this there is no need to close, you are not running a interactive program. Remove all these lines:

if i == 2:
        print 'Inside EOF block'
        if p.isalive():
            print '******************************************************'
            print '         Closing the process of Download !!!          '
            print '******************************************************\n\n'
            p.close()

The issue is that some where you have to store the password and use it with p.sendline. How ever, you store password, it is going to be insecure. You can also take the input at the start for the password, this way you will not be storing the password within your program but that defeats automation. I don't see a way out but for taking password input, you can do:

import getpass
getpass.getpass("please provide your password")
pyfunc
  • 65,343
  • 15
  • 148
  • 136
  • Thanks Pyfunc that worked like a gem. Thanks for the detailed explanation as well. Helps to understand it better.. Sorry for the late reply.. Yes that indeed worked.. But one problem although. It does not show the password when I enter but after that looks like p.logfile = sys.stdout somehow prints the password in plain text in the terminal. any ways to avoid that.. – user596922 Jun 27 '12 at 05:02
0

To get rid of the password being echo'd to stdout, use the following when redirecting output -

p.logfile_read = sys.stdout  # logs out the command  

I have tried this myself and seems to be working. Here is the reference for this revelation.

iaswtw
  • 162
  • 1
  • 9