Как сделать Web консоль Python

Как сделать доступ к консоли Python через браузер?


Ответы (1 шт):

Автор решения: eri

Для отображения терминала в браузере есть несколько готовых JS. Например, xterm.js

Нужно сделать транспорт до браузера. Websocket подойдет:

<!doctype html>
  <html>
    <head>
      <link rel="stylesheet" href="node_modules/xterm/css/xterm.css" />
      <script src="node_modules/xterm/lib/xterm.js"></script>
    </head>
    <body>
      <div id="terminal"></div>
      <script>
        const term = new Terminal();
    const socket = new WebSocket('ws://localhost:8080/term');
        term.open(document.getElementById('terminal'));
        term.onData(function(data){
        console.log(data)
        socket.send(data)
    })

    socket.addEventListener('message', function (event) {
        console.log('>', event)
        term.write(event.data);
    });

      </script>
    </body>
  </html>

Потом со стороны сервера, там пойдет aiohttp, tornado, twisted, может ещё что... Там запускаешь псевдотерминал и соединяешь его с вэбсокетом:

import asyncio
from aiohttp import web
import aiohttp
import os
import pty
import fcntl

async def websocket_handler(request):

    ws = web.WebSocketResponse()
    await ws.prepare(request)
    loop = asyncio.get_running_loop()

    master, slave = pty.openpty()

    name = os.ttyname(slave)

    pid = os.fork() 
    if pid == 0:
        os.setsid()
        os.dup2(slave,0)
        os.dup2(slave,1)
        os.dup2(slave,2)
        os._exit(os.execv('/bin/bash',('bash',)))

    stdin = os.fdopen(master, 'wb+', buffering=0)

    fl = fcntl.fcntl(master, fcntl.F_GETFL)
    fcntl.fcntl(master, fcntl.F_SETFL, fl | os.O_NONBLOCK)

    def pipe_data_received(ws):
        data = stdin.read()
        try:
            asyncio.ensure_future(ws.send_str(data.decode()))
        except:
            os.kill(pid,15)

    loop.add_reader(master, pipe_data_received, ws)

    async for msg in ws:

        if msg.type == aiohttp.WSMsgType.TEXT:
            stdin.write(msg.data.encode())

        elif msg.type == aiohttp.WSMsgType.BINARY:
            stdin.write(msg.data)

        elif msg.type == aiohttp.WSMsgType.CLOSE:
            await ws.close()
            os.kill(pid,15)

        elif msg.type == aiohttp.WSMsgType.CLOSED:
            os.kill(pid,15)
        elif msg.type == aiohttp.WSMsgType.ERROR:
            os.kill(pid,15)

    os.kill(pid,15)
    os.waitpid(pid, 0)
    return ws


app = web.Application()
app.add_routes([web.get('/term', websocket_handler)])
web.run_app(app)

И получаем такую красотулечку:

введите сюда описание изображения

mc и мышка работают и зомбей нет!

Консоль можно запускать любую:

    os._exit(os.execv('/usr/bin/ipython3',('python@ws', )))

введите сюда описание изображения

→ Ссылка