You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Flask Python API运行并终止Linux命令?

实现stop_cmd接口终止运行的命令(可行)

你的需求完全可以实现,核心问题是原代码中使用subprocess.call无法跟踪子进程,且没有保存进程引用。下面是修改后的完整代码,附带关键说明:

修改后的代码

from flask import Flask, jsonify, request
from threading import Thread  
from subprocess import Popen
import os
import signal

app = Flask(__name__)
running_process = None  # 全局变量跟踪运行的子进程

def RunCmd():
    global running_process
    # 使用Popen启动命令,开启新进程组避免孤儿进程
    running_process = Popen(
        'while true; do echo "hello"; sleep 2s; done',
        shell=True,
        start_new_session=True
    )
    running_process.wait()  # 阻塞等待进程结束

@app.route('/run_cmd', methods=['GET'])
def run_cmd():
    global running_process
    # 检查是否已有命令在运行
    if running_process is not None and running_process.poll() is None:
        return jsonify({
            "status": "error",
            "message": "已有命令在运行,无法重复启动"
        }), 400
    Thread(target=RunCmd).start()
    return jsonify({"status": "ok"}), 200

@app.route('/stop_cmd', methods=['GET'])
def stop_cmd():
    global running_process
    # 检查是否有正在运行的命令
    if running_process is None or running_process.poll() is not None:
        return jsonify({
            "status": "error",
            "message": "没有正在运行的命令"
        }), 400
    # 杀掉整个进程组(避免shell子进程变成孤儿进程继续运行)
    try:
        os.killpg(os.getpgid(running_process.pid), signal.SIGTERM)
        running_process.wait()
        running_process = None
        return jsonify({
            "status": "ok",
            "message": "命令已成功终止"
        }), 200
    except Exception as e:
        running_process = None
        return jsonify({
            "status": "error",
            "message": f"终止命令失败: {str(e)}"
        }), 500

if __name__ == '__main__':
    app.run(debug=True)

关键说明

  1. 替换subprocess.call为Popen:

    • call是阻塞式调用,会等待命令结束才返回,且无法获取进程句柄;
    • Popen启动子进程后立即返回进程对象,允许后续对进程进行终止、状态查询等操作。
  2. 进程组处理:

    • 由于使用shell=True,实际执行循环命令的是shell的子进程;若仅终止shell进程,子进程会变成孤儿进程继续运行。
    • 通过start_new_session=True创建新的进程组,再用os.killpg杀掉整个进程组,确保所有相关进程都被终止。
  3. 状态检查与全局变量:

    • 用全局变量running_process跟踪当前运行的进程,通过poll()方法判断进程是否存活(返回None表示正在运行);
    • 接口中增加状态检查,避免重复启动命令或终止不存在的进程。
  4. 部署注意事项:

    • 如果使用多worker模式部署Flask(如Gunicorn多进程),全局变量无法在worker间共享,此时需要用外部存储(如Redis)保存进程ID和状态。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 20:50:25