You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过Flask框架在Web浏览器中实时获取Linux 'top'命令的输出?

用Flask实现top命令实时输出到浏览器的方案

嘿,别着急!我刚帮朋友解决过类似的问题,用Flask实现top命令的实时输出完全可行,核心是要用到服务器推送技术——普通HTTP请求是一次性的,没法持续返回更新内容,而SSE(Server-Sent Events)就是最适合新手的轻量方案,不用复杂的双向通信。下面给你一步步拆解:

核心思路

我们需要让Flask后端持续运行top命令,把输出以流式的方式推送给浏览器;前端通过SSE连接接收这些实时数据,然后展示在页面上。

具体实现步骤

1. Flask后端代码

首先编写后端逻辑,重点是创建一个流式响应的路由,用来推送top的输出:

from flask import Flask, Response, render_template
import subprocess
import time

app = Flask(__name__)

def stream_top_output():
    # 启动top命令:-b是批处理模式(输出纯文本),-d 2是每2秒刷新一次
    top_process = subprocess.Popen(
        ['top', '-b', '-d', '2'],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        text=True
    )
    try:
        while True:
            # 读取top的一行输出
            line = top_process.stdout.readline()
            if not line:
                break  # 进程结束时退出循环
            # 按照SSE的格式返回数据:data: 内容\n\n
            yield f'data: {line}\n\n'
            time.sleep(0.1)  # 稍微控制发送频率,避免前端压力过大
    finally:
        # 确保进程被杀死,避免僵尸进程
        top_process.kill()

@app.route('/')
def index_page():
    # 返回前端页面
    return render_template('index.html')

@app.route('/stream_top')
def top_stream_route():
    # 返回SSE响应,设置正确的MIME类型
    return Response(stream_top_output(), mimetype='text/event-stream')

if __name__ == '__main__':
    # 必须开启threaded=True,否则流式响应会阻塞整个Flask服务
    app.run(debug=True, threaded=True)

2. 前端页面(templates/index.html)

然后写一个简单的前端页面,用来接收并展示实时数据:

<!DOCTYPE html>
<html>
<head>
    <title>实时Top监控</title>
    <style>
        #monitor-area {
            background-color: #f5f5f5;
            padding: 15px;
            font-family: "Consolas", "Monaco", monospace;
            height: 500px;
            overflow-y: auto;
            border-radius: 5px;
        }
    </style>
</head>
<body>
    <h1>系统实时监控(Top命令)</h1>
    <div id="monitor-area"></div>

    <script>
        // 建立SSE连接到后端的/stream_top路由
        const eventSource = new EventSource('/stream_top');
        const monitorArea = document.getElementById('monitor-area');

        // 接收后端推送的每一条数据
        eventSource.onmessage = function(event) {
            // 追加新内容到页面(如果想模拟top的刷新效果,可替换成monitorArea.textContent = event.data)
            monitorArea.textContent += event.data;
            // 自动滚动到最新内容
            monitorArea.scrollTop = monitorArea.scrollHeight;
        };

        // 处理连接错误
        eventSource.onerror = function(error) {
            console.error('SSE连接出错:', error);
            eventSource.close();
        };
    </script>
</body>
</html>

关键细节说明

  • top -b -d 2-b参数是关键,让top以批处理模式运行,输出纯文本而不是终端控制字符(不然页面会显示一堆乱码);-d 2指定刷新间隔为2秒,可根据需求调整。
  • SSE格式要求:必须以data: 内容\n\n的格式返回数据,浏览器才能正确识别为SSE事件。
  • threaded=True:Flask默认是单线程的,流式响应会阻塞整个服务,开启多线程后才能同时处理页面请求和流式推送。
  • 前端滚动:monitorArea.scrollTop = monitorArea.scrollHeight可以让页面自动滚动到最新的输出内容,体验更流畅。

生产环境注意事项

  • 不要在生产环境使用debug=True,建议用Gunicorn等WSGI服务器,启动时记得开启多线程(比如gunicorn --workers=2 --threads=4 app:app)。
  • 权限问题:确保运行Flask的用户有执行top命令的权限(一般默认用户都有,但特殊环境需要检查)。
  • 资源控制:如果长时间运行,要确保top进程能被正确销毁(代码里的finally块已经处理了这一点)。

试试这个方案,应该能解决你的实时更新问题!如果有哪里卡住了,随时问细节~

内容的提问来源于stack exchange,提问作者Stan1234

火山引擎 最新活动