Python技术迷

在浏览器里面运行命令行,真香!

其实这事儿我是前几天才发现的。当时在调一个小工具,本来想在服务器上跑个脚本,结果 SSH 连不上,我一气之下就随手搜了下“浏览器命令行”,没想到真有人整出这玩意儿。然后我一试……嗯,真香。

一、浏览器里开命令行?咋实现的?

这玩意儿其实核心思路很简单,就是在浏览器端用 WebSocket 跟后端建立实时连接,输入的命令传到后端去执行,结果再通过 Socket 实时推回来。 听起来挺绕,但整个流程其实挺顺:

  1. 浏览器这边输入命令;
  2. WebSocket 把命令发给后端;
  3. 后端 subprocess 执行命令;
  4. 执行结果再推回浏览器显示。

比如下面这段 Python Flask 的最简实现:

from flask import Flask, render_template
from flask_socketio import SocketIO, emit
import subprocess

app = Flask(__name__)
socketio = SocketIO(app)

@socketio.on('run_cmd')
defhandle_command(cmd):
try:
        result = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, text=True)
        emit('cmd_result', result)
except subprocess.CalledProcessError as e:
        emit('cmd_result', e.output)

if __name__ == '__main__':
    socketio.run(app, host='0.0.0.0', port=5000)

然后前端随便写个小页面:

<!DOCTYPE html>
<html>
<body>
<inputid="cmd"placeholder="输入命令..."/>
<buttononclick="sendCmd()">运行</button>
<preid="output"></pre>

<scriptsrc="https://cdn.socket.io/4.0.0/socket.io.min.js"></script>
<script>
const socket = io();

functionsendCmd() {
const cmd = document.getElementById("cmd").value;
      socket.emit('run_cmd', cmd);
    }

    socket.on('cmd_result', (data) => {
document.getElementById("output").textContent += data + "\n";
    });
</script>
</body>
</html>

运行之后,浏览器上输入 ls、pwd 这些命令,输出就会直接显示在页面上。真就跟开了个网页版 shell 一样。

二、为啥这么爽?

第一是——随时随地。 我那天在公司楼下买咖啡的时候,还能直接用手机浏览器执行一条命令去重启测试环境的服务(当然有权限校验哈)。

第二是——兼容性好。 不像 WebSSH 那种需要一堆配置,这个靠 Socket + Python 的标准库就能跑,轻量级,前端用 React、Vue、纯 HTML 都能整。

第三是——可控性强。 比如我后来加了个安全层,只允许执行白名单里的命令,比如:

ALLOWED_CMDS = ["ls", "pwd", "whoami"]

if cmd.split()[0] notin ALLOWED_CMDS:
    emit('cmd_result', f"命令 {cmd} 不被允许!")
return

这样就不会有人瞎搞删库跑路。

三、实际用起来的几个小坑

我这人有个毛病,啥都得试到极致。 结果在测试时发现几个问题:

  1. 命令执行阻塞用 subprocess.check_output 是同步执行的,如果命令太慢(比如 ping 或 sleep),前端就卡住了。后来换成异步的:

    import asyncio
    from flask_socketio import AsyncServer

    @socketio.on('run_cmd')
    asyncdefhandle_command(cmd):
        process = await asyncio.create_subprocess_shell(
            cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
        )
        stdout, stderr = await process.communicate()
        emit('cmd_result', (stdout or stderr).decode())
  2. 权限问题浏览器里运行命令其实是服务器在执行,所以一定要开权限控制。 我一般会加个登录 token 校验,不然任何人访问都能跑命令,风险太大。

  3. 输出实时性有些命令是持续输出的,比如 tail -f,这种得一行一行读然后实时推给前端,否则前端一直等结果。

四、真香背后的小感悟

以前总觉得命令行得有终端才叫“正统”,但现在连浏览器都能跑 shell,这体验真的改变了我。 尤其是团队协作的时候,比如前端同学调试服务器环境,不用我再帮他登录服务器,只要开个浏览器就能跑命令、看日志、改配置。 有种云端控制一切的感觉。

当然,安全性这关一定要把好。浏览器里跑命令听起来就危险,但只要做好用户认证 + 命令白名单 + 沙箱隔离,就能安全又高效。


总之,这东西用一句话总结就是:

浏览器变成你的命令行终端,方便到爆,但也得敬畏它的力量。

我自己已经打算把它封装成一个小工具,准备叫它——WebShell Lite。 有兴趣我下次把那前端界面也分享出来,真·方便到离谱。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领