0
import pexpect

domain = "test"
username = "user"
password = "password"

child = pexpect.spawn("virsh console " + domain)

# ensure we get a login prompt:
child.sendline()

# log in:
child.expect("login:")
child.sendline(username)
child.expect("Password:")
child.sendline(password)

# run command:
child.sendline("touch foo.txt")
child.sendline("exit") 

This works perfectly. The problem now is that I want to do an ls (after touch) and get the output but I can't figure out how to do that.

I saw an example using child.logfile = sys.stdout right after spawn (and changing the spawn line to include encoding="utf-8") and this does produce some output, but doesn't show the output from ls.

From here:

Python how to read output from pexpect child?

I tried the following:

import pexpect

domain = "test"
username = "user"
password = "password"

child = pexpect.spawn("virsh console " + domain)

# ensure we get a login prompt:
child.sendline()

# log in:
child.expect("login:")
child.sendline(username)
child.expect("Password:")
child.sendline(password)

# run command:
child.sendline("touch foo.txt")
child.sendline("ls")
child.expect(pexpect.EOF)
print(child.before)

child.sendline("exit")

But this just times out.

I also tried:

import pexpect

domain = "test"
username = "user"
password = "password"

child = pexpect.spawn("virsh console " + domain)

# ensure we get a login prompt:
child.sendline()

# log in:
child.expect("login:")
child.sendline(username)
child.expect("Password:")
child.sendline(password)

# run command:
child.sendline("touch foo.txt")
child.sendline("ls")
child.expect(".*") # the shell prompt varies extensively
print(child.before)

child.sendline("exit")

And this returns the following line:

b''

Which is clearly not the expected output from ls. How do I get stdout from ls in this case?

All the examples from: Python how to read output from pexpect child? do not have this extra layer of virsh console in the equation, which I think makes my problem much more difficult to solve.

cat pants
  • 1,485
  • 4
  • 13
  • 22
  • Your last code block is consistent with `expect('.*')` being tripped by the zeroth byte in the output of `ls`. Is there nothing reliable in the prompt that is not present in the output of `ls`? – Andras Deak -- Слава Україні Jan 03 '23 at 09:33
  • 1
    Thank you. I tried: `child.expect("\$")` for example, but if the command is `ls` and for example a file has `$` in the filename, the output will not be correct. I realize now it is likely impossible for python to simply "just give me stdout" as the command passes through virsh console. My approach must therefore focus on reconsidering what shell prompts are expected and making the expect regex as specific as possible. – cat pants Jan 03 '23 at 19:07
  • 1
    This leads to some really strange edge cases, for example, if for some reason a server had the prompt set to simply `abc` then getting `ls` output would fail on filename `abc`. But for something like this, no workaround is even *possible* I don't think. Python has no way to know what stdout is, the only way it can tell is by parsing the text itself, I just have to hope all shell prompts are "reasonable". (And they likely are, it's just me wanting to avoid really ugly edge cases / potential for bugs) – cat pants Jan 03 '23 at 19:11
  • Indeed, this looks unmanageable in the completely general case. – Andras Deak -- Слава Україні Jan 03 '23 at 22:55

0 Answers0