pexpect to automate login to pbrun

2.1k views Asked by At

I am trying to automate pbrun using the following code

ssh [email protected]
pbrun -u user1 bash
pass active directory password
run the command
exit

I created the following script but it's not able to pass the password for pbrun:

import time
import pexpect
child = pexpect.spawn('ssh [email protected]')
child.expect("[email protected]'s password:")
child.sendline('Password')
child.expect ('.')
child = pexpect.spawn ('pbrun -u user1 bash')
child.expect ('.*')
time.sleep(10)
child.sendline ('Password') - Active directory password
child.expect ('.*')
child.sendline ('ls')
data = child.readline('ls')
print data

The above code successfully does ssh and runs pbrun but is unable to send the password asked by pbrun. Any help is appreciated.

2

There are 2 answers

0
user3754136 On BEST ANSWER

I was able to achieve this by below script, tried python but was not successful, sharing this script which may be helpful to others.

#!/usr/bin/expect -f

if { $argc<1 } {
        send_user "usage: $argv0 <passwdfile> \n"
        exit 1
}
set timeout 20
set passwdfile [ open [lindex $argv 0] ]
catch {spawn -noecho ./myscript.sh}
expect "Password:" {
        while {[gets $passwdfile passwd] >= 0} {
                send "$passwd\r"
                }
}
expect "*]$\ " {send "exit\r"}
close $passwdfile
send "ls\r"
expect eof

Run the script as below:

./run.exp passfile.txt

here passfile.txt has the password in text and myscript.sh has the pbrun command

0
Dan Cornilescu On

In general it's not a great idea to expect wildcards like . or .* because those can match a partial input and your script will continue and send its next line potentially before the server at the other end is even able to receive/handle it, causing breakage. Be as specific as possible, ideally trying to match the end of whatever the server sends right before it waits for input.

You have access to the string buffers containing what pexpect receives before and after the matched pattern in each child.expect() statement with the following constructs which you can print/process at will:

print child.before
print child.after

You might want to get familiar with them - they're your friends during development/debugging, maybe you can even use them in the actual script implementation.

Using sleeps for timing is not great either - most of the time they'll just unnecessarily slow down your script execution and sooner or later things will move at different/unexpected speeds and your script will break. Better expect patterns eventually with a timeout exception are generally preferred instead - I can't think of a case in which sleeps would be just as (or more) reliable.

Check your script's exact communication using these techniques and adjust your patterns accordingly.