杀死一个 python 没有 return 的子进程

Kill a python subprocess that does not return

TLDR 我想在它还在 运行ning
时杀死像 top 这样的子进程 我正在使用 Fastapi 运行 输入命令。例如,如果我在我的程序顶部输入 运行s 命令,但由于它没有 return,此时我必须使用时间延迟然后 kill/terminate 它。但是,我希望能够在它还在 运行ning 时将其杀死。但是目前它不会 运行 我的 kill 命令,直到 运行 结束。 这是 运行 进程的当前代码:

@app.put("/command/{command}")
async def run_command(command: str):
    subprocess.run([command], shell=True, timeout=10)
    return {"run command"}

并杀死它

@app.get("/stop")
async def stop():
    proc.kill()
    return{"Stop"}

我是 fastapi 的新手,所以如果有任何帮助,我将不胜感激

这是因为 subprocess.run 正在阻止自己 - 您需要在后台执行 运行 shell 命令,例如如果你已经打开了 asnycio 循环,你可以使用 subprocesses

import asyncio

process = None
@app.get("/command/{command}")
async def run_command(command: str):
    global process
    process = await asyncio.create_subprocess_exec(
        command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
    )
    return {"run command"}

@app.get("/stop")
async def stop():
    process.kill()
    return {"Stop"}

Popen

from subprocess import Popen

process = None
@app.get("/command/{command}")
async def run_command(command: str):
    global process
    process = Popen([command])  # something long running
    return {"run command"}

添加超时选项可能会很棘手,因为您不想等到它完成(您确实可以使用 wait_for 函数),而是在特定时间后终止进程。据我所知,最好的选择是安排负责杀死主要进程的其他进程。使用 asyncio 的代码可能如下所示:

@app.get("/command/{command}")
async def run_command(command: str):
    global process
    process = await asyncio.create_subprocess_exec(
        command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
    )
    loop = asyncio.get_event_loop()
    # We schedule here stop coroutine execution that runs after TIMEOUT seconds
    loop.call_later(TIMEOUT, asyncio.create_task, stop(process.pid))

    return {"run command"}

@app.get("/stop")
async def stop(pid=None):
    global process
    # We need to make sure we won't kill different process
    if process and (pid is None or process.pid == pid):
        process.kill()
        process = None
    return {"Stop"}