Skip to content

Instantly share code, notes, and snippets.

@eliangcs
Last active January 7, 2020 08:48
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save eliangcs/0b253675759c97b5b842 to your computer and use it in GitHub Desktop.
Save eliangcs/0b253675759c97b5b842 to your computer and use it in GitHub Desktop.
A minimal web server that runs shell commands, powered by Tornado and its Subprocess module
"""
A minimal web server that runs shell commands, powered by Tornado and its
Subprocess module. It does non-blocking IO and streams the response.
To start the server:
$ python tornado_subprocess.py
To send a shell command using httpie:
$ echo 'ls -l /' | http POST http://localhost:8899 --stream
"""
import shlex
import tornado.ioloop
import tornado.web
from tornado import gen
from tornado.iostream import StreamClosedError
from tornado.process import Subprocess
class MainHandler(tornado.web.RequestHandler):
@gen.coroutine
def post(self):
cmd = shlex.split(self.request.body)
yield self.run_subprocess(cmd)
@gen.coroutine
def run_subprocess(self, cmd):
proc = Subprocess(cmd, stdout=Subprocess.STREAM,
stderr=Subprocess.STREAM)
yield self.redirect_stream(proc.stdout)
yield self.redirect_stream(proc.stderr)
@gen.coroutine
def redirect_stream(self, stream):
while True:
try:
data = yield stream.read_bytes(128, partial=True)
except StreamClosedError:
break
else:
self.write(data)
self.flush()
def make_app():
return tornado.web.Application([
(r'/', MainHandler)
])
if __name__ == "__main__":
app = make_app()
app.listen(8899)
tornado.ioloop.IOLoop.current().start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment