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.
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