Search code examples
pythonbashsshterminalclient-server

Pseudo terminal will not be allocated error - ssh - sudo - websocket - subprocess


I basically want to create a web page through which a unix terminal at the server side can be reached and commands can be sent to and their results can be received from the terminal.

For this, I have a WSGIServer. When a connection is opened, I execute the following:

def opened(self):
        self.p = Popen(["bash", "-i"], bufsize=1, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
        self.p.stdout = Unbuffered(self.p.stdout)

        self.t = Thread(target=self.listen_stdout)
        self.t.daemon = True
        self.t.start()

When a message comes to the server from the client, It is handled in the following function, which only redirects the coming message to the stdin of subprocess p which is an interactive bash:

def received_message(self, message):
    print(message.data, file=self.p.stdin)

Then outputs of the bash is read in the following function within a separate thread t. It only sends the outputs to the client.

def listen_stdout(self):
    while True:
        c = self.p.stdout.read(1)
        self.send(c)

In such a system, I am able to send any command(ls, cd, mkdir etc.) to the bash working at the server side and receive their outputs. However, when I try to run ssh xxx@xxx, the error pseudo-terminal will not be allocated because stdin is not a terminal is shown.

Also, in a similar way, when I run sudo ..., the prompt for password is not sent to the client somehow, but it appears on the terminal of the server script, instead.

I am aware of expect; however, only for such sudo and ssh usage, I do not want to mess my code up with expect. Instead, I am looking for a general solution that can fake sudo and ssh and redirect prompt's to the client.

Is there any way to solve this? Ideas are appreciated, thanks.


Solution

  • I found the solution. What I need was creating a pseudo-terminal. And, at the slave side of the tty, make a setsid() call to make this process a new session and run commands on it.

    Details are here: http://www.rkoucha.fr/tech_corner/pty_pdip.html