Reputation: 3009
I am trying to implement a sort of reverse terminal: start server.py on some computer foo.
On some other computer run nc foo 2000 and you are connected to a bash shell on foo.
I am using the following server code:
import socket,os,threading,select,subprocess
class mysocket(socket.socket):
def __init__(self,*arg, **kw):
super(mysocket,self).__init__(*arg, **kw)
self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.setblocking(0)
def read(self):
return self.recv(2048)
def write(self,data):
self.send(data)
def accept(self):
conn,addr = super(mysocket,self).accept()
return mysocket(_sock=conn),addr
socket.socket = mysocket
import SocketServer
class RequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
subprocess.call(['bash','-i'],env=os.environ,stdin=self.request,stdout=self.request,stderr=self.request)
class ForkedTCPServer(SocketServer.ForkingMixIn, SocketServer.TCPServer):
pass
if __name__ == '__main__':
address = ('0.0.0.0', 2000) # let the kernel give us a port
server = ForkedTCPServer(address, RequestHandler)
server.serve_forever()
This works great if you only do one connection at a time.
However when I open a second connection, the nc program sits waiting, and my python process has the message:
[1]+ Stopped python server.py
If I type %1 to bring the process to the foreground, then the second nc screen starts working and I have two remote bash shells.
My question is why does the python process get stopped, and how can I stop it from happening?
As far as I can tell nothing is blocking, because once I resurrect the process everything works perfectly!
Thanks much.
Upvotes: 0
Views: 413
Reputation: 3009
I figured it out. The problem was with calling bash, as other things would work.
Eventually on a whim I tried calling bash with the script command and it worked as expected.
Here is some final code for anyone who wants it:
import socket,os,threading,subprocess
class mysocket(socket.socket):
def __init__(self,*arg, **kw):
super(mysocket,self).__init__(*arg, **kw)
self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
def read(self):
return self.recv(2048)
def write(self,data):
self.send(data)
def accept(self):
conn,addr = super(mysocket,self).accept()
return mysocket(_sock=conn),addr
socket.socket = mysocket
import SocketServer
class RequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
subprocess.call('script -q -f -c "bash -i" /dev/null',shell=True,env=os.environ,stdin=self.request,stdout=self.request,stderr=self.request)
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
if __name__ == '__main__':
address = ('0.0.0.0', 2000)
server = ThreadedTCPServer(address, RequestHandler)
server.serve_forever()
Note that this does not work on windows because of python's lack of support for using sockets as files on that platform. However it works perfectly on cygwin. Just install python and util-linux (for the script command) from cygwin's setup.exe.
Upvotes: 2