Pankaj Sheoran
Pankaj Sheoran

Reputation: 39

Run linux command from python which needs user input

I have following python code:

import subprocess
p=subprocess.Popen(["openssl","genrsa","-aes256","-out","ise.key.pem","2048"],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
inputdata="123456"
p.communicate(input=inputata)
p.communicate(input=inputata)

output of above code is:

    pan@pan:~/python-scripts$ Generating RSA private key, 2048 bit long modulus
........................+++
...................................+++
e is 65537 (0x10001)
Enter pass phrase for ise.key.pem:
User interface error
140617148802712:error:0906906F:PEM routines:PEM_ASN1_write_bio:read key:pem_lib.c:379:

I want that input should be give by python there should not be any user interaction :

I know certificate can be generated by python pyOpenSSL library but I want to use normal linux command

My python version is:

Python 2.7.12 (default, Dec  4 2017, 14:50:18) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "enter code here`license" for more information.

I saw following link but it didn't help

Python execute command line,sending input and reading output

If you run the command in shell it runs as below:

pan@pan:~/python-scripts$ openssl genrsa -aes256 -out ise.key.pem 2048
Generating RSA private key, 2048 bit long modulus
..............................................................+++
..+++
e is 65537 (0x10001)
Enter pass phrase for ise.key.pem:
Verifying - Enter pass phrase for ise.key.pem:

Upvotes: 2

Views: 1926

Answers (2)

Gioachino Bartolotta
Gioachino Bartolotta

Reputation: 123

I usually don't like subprocess for this kind of tasks ... I would prefer to use pexpect to emulate human behaviour (typing in data ... and so on).

This one is a rough example to do the job

import pexpect

def main():
        inputdata="123456"
        c = pexpect.spawn("/usr/bin/openssl", ["genrsa","-aes256","-out","ise.key.pem","2048"])
        c.expect("Enter.*:")
        c.sendline(inputdata)
        c.expect("Verifying.*:")
        c.sendline(inputdata)
        c.expect(pexpect.EOF)
        c.close()
        c.kill(0)
        print "Done"

if __name__=='__main__':
        main()

Upvotes: 0

Armali
Armali

Reputation: 19375

In his comment, Jean-François Fabre is right about this:

But the real issue is that piping input to a password entering routine doesn't always work.

But not about this:

You have to generate a keyboard event at a lower level.

Though it would be true in general, in the case at hand the command openssl genrsa … offers the option -passout stdin to read the password from standard input:

openssl genrsa -aes256 -out ise.key.pem -passout stdin 2048

So, this Python script works:

import subprocess
p=subprocess.Popen(["openssl","genrsa","-aes256","-out","ise.key.pem",
                    "-passout","stdin","2048"], stdin=subprocess.PIPE,
                                                stdout=subprocess.PIPE)
inputdata="123456"
p.communicate(input=inputdata)

Note that one cannot call communicate() with timeout=None more than once, since it waits for process to terminate. But it isn't necessary either, because with -passout stdin the command doesn't ask for verifying, thus no need to enter the pass phrase a second time.

Upvotes: 0

Related Questions