Search code examples
pythonlinuxsubprocesspopenprompt

Using subprocess to execute a linux command in python and then grab the resulting prompt


I am using subprocces.Popen() to run linux commands in python. I am trying to use this command to ssh into a different machine, and see whether it prompts me for a password.

However, I have no idea how to grab the resulting prompt and use it in the python script.

For example, if I use subprocess.Popen() to call the command "echo Hello World" I can then use the communicate() method to grab the resulting stdout from running that command.

But here is what I am trying to do: use Popen() to run: ssh -hostname- 'echo Hello' and then grab the result of that for use within the python script. So if the ssh runs into a prompt for the password, I want to be able to have the output of that prompt in the python script to use as a string. Finally, I want to be able to exit out of this prompt (equivalent of typing ^C when using linux terminal). However, when using Popen() and communicate(), it simply just shows the prompt on the actual linux stdout and doesn't grab the prompt.

I was also hoping to suppress this prompt from ever showing on the actual linux terminal stdout.

Here is the code that I have been using (this code works when grabbing normal stdout):

p = subprocess.Popen(["ssh", hostName, "echo Hello"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
sshOutput, err = p.communicate()

Of course, the password prompt is not stored in sshOutput, which is the issue. If I ran the following command, result would be a string containing "Hello"

p = subprocess.Popen(["echo", "Hello"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
result, err = p.communicate()

Solution

  • The problem is that ssh prints prompt and reads password from current tty, not stdout/stdin. See this question.

    Possible solutions:

    • Connect ssh's stdin and stdout to a slave pty and read/write master pty from your application. You can use expect or pexpect (in Python).
    • Run ssh inside some wrapper program that will insert a pty between it's stdin/stdout and ssh's stdin/stdout. Maybe unbuffer will work. In this case you can continue using subprocess.
    • Use sshpass. You can also use this with subprocess.