pythonpexpect

Pass Multiple Inputs to Terminal Command Python


I have this terminal command I need to run programmatically in Python:

awssaml get-credentials --account-id **** --name **** --role **** --user-name ****

It will first ask for your password, and then prompt you for a 2 factor authentication code. I have these as variables in python that I just need to pass through to the command.

This is what I tried:

   argss=[str(password_entry.get()),str(twoFactorCode_entry.get())]
   p=subprocess.Popen(["awssaml", "get-credentials", "--account-id", "****", "--name", "****", "--role", "****", "--user-name", ID_entry.get()],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
   time.sleep(0.1)
   
   out=p.communicate('\n'.join(map(str,argss)).encode())

And when I run this the console prints out that the password was entered because it shows password: xxxxxxxxxxxx, but it then stops execution and does not show the 2 factor code being passed.

Any ideas for where I am going wrong to get the 2 factor code also passed through? Both the password and 2 factor code are within the argss variable. password_entry.get() is the password and twoFactorCode_entry.get() is the 2 factor code.

This is what the first prompt looks like:

enter image description here

And I was trying this child.expect('password:') which gives this error:

after: <class 'pexpect.exceptions.TIMEOUT'>
match: None
match_index: None
exitstatus: None
flag_eof: False
pid: 66502
child_fd: 10
closed: False
timeout: 30
delimiter: <class 'pexpect.exceptions.EOF'>
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1
searcher: sear

Solution

  • I would recommend using something like pexpect for this since it ends up being a bit complicated.

    import pexpect
    
    p=pexpect.spawn('awssaml', ["get-credentials", "--account-id", "****", "--name", "****", "--role", "****", "--user-name", ID_entry.get()])
    p.expect('<whatever the prompt is for password>')
    p.sendline(str(password_entry.get()))
    p.expect('<whatever the prompt is for 2 factor code>')
    p.sendline(str(twoFactorCode_entry.get()))
    

    pexpect is descended from the expect Tcl library which is really designed for automating interactive CLI programs unlike the default Python subprocess module.