Matteo Matteo - 1 month ago 4
Python Question

Using expect to get output from ssh

I am trying to use

expect
to automate a task as part of a larger python program and am having a lot of trouble getting the stdout of the ssh command being run on a remote machine. I have not used
expect
before and haven't had success finding the solution on the man page.

I need to use expect to automate some interactions before actually being able to run this command, but I removed them here to simplify the question.

Here is a simplified example of the program:

import subprocess

expect = """
/usr/bin/expect <<EOF

spawn ssh some_machine ls
expect eof
puts "$expect_out(buffer)"
"""

output = subprocess.check_output(expect, shell=True)
print(output)


Output:

b'spawn ssh some_machine ls\r\n116029\r\nArchive\r\n\r\n(buffer)\n'


It appears to contain the spawn command as well as "(buffer)" at the end. I'm not sure why this is occurring. I am trying to only get the results of the
ls
.

If I turn on debug mode in expect, I see the
expect_out(buffer)
being set to what I would like to return, but the
puts
does not reflect this.

Output:

expect version 5.45
argv[0] = /usr/bin/expect argv[1] = -d
set argc 0
set argv0 "/usr/bin/expect"
set argv ""
executing commands from command file
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {1753}
expect: read eof
expect: set expect_out(spawn_id) "exp7"
expect: set expect_out(buffer) "116029\r\nArchive\r\n"
<wrong output as above>

Answer

You can suppress the log output from expect with the log_user command:

log_user 0
spawn ssh some_host ls
expect eof
puts "$expect_out(buffer)"

Without log_user 0, I get:

$ expect -f sample.tcl
spawn ssh some_host ls
file1
file2

By adding log_user 0, I get:

$ expect -f sample.tcl
file1
file2

There seems to be some oddness when you feed expect the script via stdin, but the following seems to work:

import subprocess
import tempfile

expect = """
log_user 0
spawn ssh some_host ls < /dev/null
expect eof
puts "$expect_out(buffer)"
"""

with tempfile.NamedTemporaryFile() as fd:
    fd.write(expect)
    fd.flush()
    fd.seek(0)
    output = subprocess.check_output(['expect', fd.name])

print(output)
Comments