Currently the c.read() function only returns values from output of the program that I am calling and does not collect what happens during the interactive portion. (In other words: Waiting for user name and password). Since errors can happen during that section I need to collect all output after the cmd is called.
Using the run command works fine. I am trying to convert to using expect.spawn() since that looks very close to the ssh version of expect. Current the run() method works fine in that it works locally. I can't find getOutput() type function that would return the entire output.
import pexpect
class Expect( ):
def Do( self, cmd, program: list = [], timeout: int = 20 ):
# result = run( cmd, events=program, timeout=timeout).decode()
result = ''
c = pexpect.spawn( cmd, encoding='utf-8', timeout=timeout )
for curItem in program:
# print( 'wait: ' + curItem[0] + ' resp: ' + curItem[1])
c.expect( curItem[0] )
c.sendline( curItem[1] )
# result += c.read()
result += c.read()
print ( 'res: ' + str(result) )
return result
cmd = 'fmsadmin list files -s'
prog = [('username \\(.+\\):', 'yourUN\n'), ('password:', 'yourPW\n')]
res = Expect().Do( cmd, prog ) # Returns everything
# use results to verify functionality
Results
ID File Clients Size Status Enabled Extended Privileges Encrypted
1 FMServer_Sample.fmp12 0 905216 Normal fmapp fmxml fmphp fmwebdirect No
When I expect
username (yourUN):yourUN
password:
ID File Clients Size Status Enabled Extended Privileges Encrypted
1 FMServer_Sample.fmp12 0 905216 Normal fmapp fmxml fmphp fmwebdirect No
Update
I added result += c.before + c.after just under c.sendline( curItem[1] ) which now returns: c.sendline( curItem[1] )
username (yourUN): yourUN
password:
ID File Clients Size Status Enabled Extended Privileges Encrypted
1 FMServer_Sample.fmp12 0 905216 Normal fmapp fmxml fmphp fmwebdirect No
Unfortunately there are still two issues. 1 there are additional values such as returns in the output and if I provide an invalid password I get debugging details back without the apps returned values. I get:
before (last 100 chars): '\r\n/usr/local/bin/fmsadmin: Permission denied, please try again.\r\nusername (yourUN):'
after: <class 'pexpect.exceptions.TIMEOUT'>
match: None
match_index: None
etc
So in short, I'm looking for the full returned values from the CLI exactly as it would be returned if I did it by hand. Which is what run() does.
OK, I figured it out. Not quite expected but it makes sense. Several changes:
I'll probably remove the local section in next version (once I figure out remote case)
from pexpect import *
class Expect( ):
def Do( self, cmd, program: list = [], timeout: int = 20 ):
local = False
result = ''
if local:
result = runu( cmd, events=program, timeout=timeout )
else:
c = ''
try:
c = spawnu( cmd, timeout=timeout )
for curItem in program:
c.expect( curItem[0] )
c.sendline( curItem[1] )
result += c.before + c.after
result += c.read()
except:
result += c.buffer
return result
cmd = 'fmsadmin list files -s'
prog = [('username \\(.+\\):', 'yourUN\n'), ('password:', 'yourPW\n')]
res = Expect().Do( cmd, prog, 5 )
print ( '-' * 50 + '\n' + str(res))