How to redirect data to a "getpass" like password input?

5.9k views Asked by At

I'm wring a python script for running some command. Some of those commands require user to input password, I did try to input data in their stdin, but it doesn't work, here is two simple python program represent the problem

input.py

import getpass

print raw_input('text1:')
print getpass.getpass('pass1:')
print getpass.getpass('pass2:')

put_data.py

import subprocess
import getpass

def run(cmd, input=None):
    stdin=None
    if input:
        stdin=subprocess.PIPE
    p = subprocess.Popen(cmd, shell=True, stdin=stdin)
    p.communicate(input)
    if p.returncode:
        raise Exception('Failed to run command %r' % cmd)

input ="""text1
password1
password2
"""
run('python test.py', input)

And here is the output

[guest@host01 ~]# python put_data.py 
text1:text1
pass1:

It just stop there on the pass1 field. Here is the problem, why I can't put data to stdin to feed data to the password field? How can I write data to password fields?

2

There are 2 answers

0
user225312 On BEST ANSWER

You need the pexpect module for such cases.

Pexpect is a Python module for spawning child applications and controlling them automatically. Pexpect can be used for automating interactive applications such as ssh, ftp, passwd, telnet, etc.

1
SuperFamousGuy On

There's definitely no need for two classes to make something like this. All you'd need to do is create another method in put_data.py called init_() and then do something along the lines of:

x = raw_input('text1:')
y = getpass.getpass('pass1:')
z = getpass.getpass('pass2:')

Then you can just use pexpect to do the rest:

child = pexpect.spawn(x, timeout=180)
while True:
   x = child.expect(["(current)", "new", "changed", pexpect.EOF, pexpect.TIMEOUT])
   if x is 0:
      child.sendline(y)
      time.sleep(1)
   if x is 1:
      child.sendline(z)
      time.sleep(1)
   if x is 2:
      print "success!"
      break

tada! Granted you'll probably get a ton of errors with code like that. You should always utilize the provided methods, if you're using linux it may just be easier to run os.system("passwd") and let the shell take care of the rest. Also, if at all possible always avoid using getpass, it's a funky obsolete method and can mess things up down the road.